[
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: cargo\n    directory: /\n    schedule:\n      interval: monthly\n    open-pull-requests-limit: 10\n    update-types: major\n  - package-ecosystem: github-actions\n    directory: /\n    schedule:\n      interval: monthly\n"
  },
  {
    "path": ".github/workflows/ci.yaml",
    "content": "name: CI\non: merge_group\n\njobs:\n\n  check:\n    name: Check (1.80.0)\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v5\n      - uses: dtolnay/rust-toolchain@1.80.0\n      - run: cp ci/compat-Cargo.lock ./Cargo.lock\n      - run: cargo check --verbose --locked\n\n  test:\n    name: Test\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        os: [ubuntu-latest, windows-latest, macos-latest]\n        rust: [stable, beta, nightly]\n    steps:\n      - uses: actions/checkout@v5\n      - uses: dtolnay/rust-toolchain@master\n        with:\n          toolchain: ${{ matrix.rust }}\n      - run: cargo build --verbose\n      - run: cargo test --verbose --package rayon\n      - run: cargo test --verbose --package rayon-core\n      - run: ./ci/highlander.sh\n\n  # rayon-demo has huge dependencies, so limit its testing.\n  # build on stable, test on nightly (because of #[bench])\n  demo:\n    name: Demo\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        rust: [stable, nightly]\n    steps:\n      - uses: actions/checkout@v5\n      - uses: dtolnay/rust-toolchain@master\n        with:\n          toolchain: ${{ matrix.rust }}\n      - run: cargo build --verbose --package rayon-demo\n      - run: cargo test --verbose --package rayon-demo\n        if: matrix.rust == 'nightly'\n\n  i686:\n    name: Test (ubuntu-latest, stable-i686)\n    runs-on: ubuntu-latest\n    steps:\n      - run: |\n          sudo apt-get update\n          sudo apt-get install gcc-multilib\n      - uses: actions/checkout@v5\n      - uses: dtolnay/rust-toolchain@stable\n        with:\n          targets: i686-unknown-linux-gnu\n      - run: cargo build --verbose --target i686-unknown-linux-gnu\n      - run: cargo test --verbose --target i686-unknown-linux-gnu --package rayon\n      - run: cargo test --verbose --target i686-unknown-linux-gnu --package rayon-core\n\n  # wasm32-unknown-unknown builds, and even has the runtime fallback for\n  # unsupported threading, but we don't have an environment to execute in.\n  wasm:\n    name: WebAssembly (standalone)\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        include:\n          - toolchain: stable\n          - toolchain: nightly\n            cargoflags: --features web_spin_lock\n            rustflags: -C target-feature=+atomics,+bulk-memory,+mutable-globals\n    env:\n      RUSTFLAGS: ${{ matrix.rustflags }}\n    steps:\n      - uses: actions/checkout@v5\n      - uses: dtolnay/rust-toolchain@master\n        with:\n          toolchain: ${{ matrix.toolchain }}\n          targets: wasm32-unknown-unknown\n      - run: cargo build --verbose --target wasm32-unknown-unknown ${{ matrix.cargoflags }}\n\n  # wasm32-wasip1 can test the fallback by running in wasmtime.\n  wasi:\n    name: WebAssembly (WASI)\n    runs-on: ubuntu-latest\n    env:\n      CARGO_TARGET_WASM32_WASIP1_RUNNER: /home/runner/.wasmtime/bin/wasmtime\n    steps:\n      - uses: actions/checkout@v5\n      - uses: dtolnay/rust-toolchain@stable\n        with:\n          targets: wasm32-wasip1\n      - run: curl https://wasmtime.dev/install.sh -sSf | bash -s -- --version v35.0.0\n      - run: cargo build --verbose --target wasm32-wasip1\n      - run: cargo test --verbose --target wasm32-wasip1 --package rayon\n      - run: cargo test --verbose --target wasm32-wasip1 --package rayon-core\n\n  fmt:\n    name: Format\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v5\n      - uses: dtolnay/rust-toolchain@1.80.0\n        with:\n          components: rustfmt\n      - run: cargo fmt --all --check\n\n  # One job that \"summarizes\" the success state of this pipeline. This can then be added to branch\n  # protection, rather than having to add each job separately.\n  success:\n    name: Success\n    runs-on: ubuntu-latest\n    needs: [check, test, demo, i686, wasm, wasi, fmt]\n    # Github branch protection is exceedingly silly and treats \"jobs skipped because a dependency\n    # failed\" as success. So we have to do some contortions to ensure the job fails if any of its\n    # dependencies fails.\n    if: always() # make sure this is never \"skipped\"\n    steps:\n      # Manually check the status of all dependencies. `if: failure()` does not work.\n      - name: check if any dependency failed\n        run: jq --exit-status 'all(.result == \"success\")' <<< '${{ toJson(needs) }}'\n"
  },
  {
    "path": ".github/workflows/main.yaml",
    "content": "name: main\non:\n  push:\n    branches:\n      - main\n  schedule:\n    - cron: '0 0 * * 0' # 00:00 Sunday\n\njobs:\n\n  test:\n    name: Test (stable)\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v5\n      - uses: dtolnay/rust-toolchain@stable\n        with:\n          toolchain: stable\n          profile: minimal\n          override: true\n      - run: cargo build --verbose\n      - run: cargo test --verbose --package rayon\n      - run: cargo test --verbose --package rayon-core\n      - run: ./ci/highlander.sh\n"
  },
  {
    "path": ".github/workflows/pr.yaml",
    "content": "name: PR\non: pull_request\n\n# Using 16MB stacks for deep test/debug recursion\nenv:\n  RUST_MIN_STACK: 16777216\n\njobs:\n\n  check:\n    name: Check (1.80.0)\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v5\n      - uses: dtolnay/rust-toolchain@1.80.0\n      - run: cp ci/compat-Cargo.lock ./Cargo.lock\n      - run: cargo check --verbose --locked\n\n  test:\n    name: Test (stable)\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v5\n      - uses: dtolnay/rust-toolchain@stable\n      - run: cargo build --verbose\n      - run: cargo test --verbose --package rayon\n      - run: cargo test --verbose --package rayon-core\n      - run: ./ci/highlander.sh\n\n  fmt:\n    name: Format\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v5\n      - uses: dtolnay/rust-toolchain@1.80.0\n        with:\n          components: rustfmt\n      - run: cargo fmt --all --check\n\n  # One job that \"summarizes\" the success state of this pipeline. This can then be added to branch\n  # protection, rather than having to add each job separately.\n  success:\n    name: Success\n    runs-on: ubuntu-latest\n    needs: [check, test, fmt]\n    # Github branch protection is exceedingly silly and treats \"jobs skipped because a dependency\n    # failed\" as success. So we have to do some contortions to ensure the job fails if any of its\n    # dependencies fails.\n    if: always() # make sure this is never \"skipped\"\n    steps:\n      # Manually check the status of all dependencies. `if: failure()` does not work.\n      - name: check if any dependency failed\n        run: jq --exit-status 'all(.result == \"success\")' <<< '${{ toJson(needs) }}'\n"
  },
  {
    "path": ".gitignore",
    "content": "Cargo.lock\ntarget\n*~\nTAGS\n*.bk\n.idea"
  },
  {
    "path": "Cargo.toml",
    "content": "[package]\nname = \"rayon\"\nversion = \"1.11.0\"\ndescription = \"Simple work-stealing parallelism for Rust\"\ndocumentation = \"https://docs.rs/rayon/\"\nexclude = [\"/ci/*\", \"/.github/*\"]\n\ncategories.workspace = true\nedition.workspace = true\nkeywords.workspace = true\nlicense.workspace = true\nreadme.workspace = true\nrepository.workspace = true\nrust-version.workspace = true\n\n[features]\n# This feature switches to a spin-lock implementation on the browser's\n# main thread to avoid the forbidden `atomics.wait`.\n#\n# Only useful on the `wasm32-unknown-unknown` target.\nweb_spin_lock = [\"dep:wasm_sync\", \"rayon-core/web_spin_lock\"]\n\n[dependencies]\n# These are both public dependencies!\nrayon-core = { version = \"1.13.0\", path = \"rayon-core\" }\neither.workspace = true\n\nwasm_sync = { workspace = true, optional = true }\n\n[dev-dependencies]\nrand.workspace = true\nrand_xorshift.workspace = true\n\n\n[workspace]\nmembers = [\"rayon-demo\", \"rayon-core\"]\nexclude = [\"ci\"]\n\n[workspace.package]\nreadme = \"README.md\"\nrust-version = \"1.80\"\nedition = \"2021\"\nlicense = \"MIT OR Apache-2.0\"\nrepository = \"https://github.com/rayon-rs/rayon\"\nkeywords = [\"parallel\", \"thread\", \"concurrency\", \"join\", \"performance\"]\ncategories = [\"concurrency\"]\n\n# Some dependencies may not be their latest version, in order to support older rustc.\n[workspace.dependencies]\ncrossbeam-deque = \"0.8.1\"\ncrossbeam-utils = \"0.8.0\"\neither = { version = \"1\", default-features = false }\nlibc = \"0.2\"\nrand = \"0.9\"\nrand_xorshift = \"0.4\"\nscoped-tls = \"1.0\"\nwasm_sync = \"0.1.0\"\n"
  },
  {
    "path": "FAQ.md",
    "content": "# Rayon FAQ\n\nThis file is for general questions that don't fit into the README or crate docs.\n\n## How many threads will Rayon spawn?\n\nBy default, Rayon uses the same number of threads as the number of CPUs\navailable. Note that on systems with hyperthreading enabled this equals the\nnumber of logical cores and not the physical ones.\n\nIf you want to alter the number of threads spawned, you can set the\nenvironmental variable `RAYON_NUM_THREADS` to the desired number of threads or\nuse the\n[`ThreadPoolBuilder::build_global` function](https://docs.rs/rayon/*/rayon/struct.ThreadPoolBuilder.html#method.build_global)\nmethod.\n\n## How does Rayon balance work between threads?\n\nBehind the scenes, Rayon uses a technique called **work stealing** to try and\ndynamically ascertain how much parallelism is available and exploit it. The idea\nis very simple: we always have a pool of worker threads available, waiting for\nsome work to do. When you call `join` the first time, we shift over into that\npool of threads. But if you call `join(a, b)` from a worker thread W, then W\nwill place `b` into its work queue, advertising that this is work that other\nworker threads might help out with. W will then start executing `a`.\n\nWhile W is busy with `a`, other threads might come along and take `b` from its\nqueue. That is called *stealing* `b`. Once `a` is done, W checks whether `b` was\nstolen by another thread and, if not, executes `b` itself. If W runs out of jobs\nin its own queue, it will look through the other threads' queues and try to\nsteal work from them.\n\nThis technique is not new. It was first introduced by the [Cilk project][cilk],\ndone at MIT in the late nineties. The name Rayon is an homage to that work.\n\n[cilk]: http://supertech.csail.mit.edu/cilk/\n\n## What should I do if I use `Rc`, `Cell`, `RefCell` or other non-Send-and-Sync types?\n\nThere are a number of non-threadsafe types in the Rust standard library, and if\nyour code is using them, you will not be able to combine it with Rayon.\nSimilarly, even if you don't have such types, but you try to have multiple\nclosures mutating the same state, you will get compilation errors; for example,\nthis function won't work, because both closures access `slice`:\n\n```rust\n/// Increment all values in slice.\nfn increment_all(slice: &mut [i32]) {\n    rayon::join(|| process(slice), || process(slice));\n}\n```\n\nThe correct way to resolve such errors will depend on the case. Some cases are\neasy: for example, uses of [`Rc`] can typically be replaced with [`Arc`], which\nis basically equivalent, but thread-safe.\n\nCode that uses `Cell` or `RefCell`, however, can be somewhat more complicated.\nIf you can refactor your code to avoid those types, that is often the best way\nforward, but otherwise, you can try to replace those types with their threadsafe\nequivalents:\n\n- `Cell` -- replacement: `AtomicUsize`, `AtomicBool`, etc\n- `RefCell` -- replacement: `RwLock`, or perhaps `Mutex`\n\nHowever, you have to be wary! The parallel versions of these types have\ndifferent atomicity guarantees. For example, with a `Cell`, you can increment a\ncounter like so:\n\n```rust\nlet value = counter.get();\ncounter.set(value + 1);\n```\n\nBut when you use the equivalent `AtomicUsize` methods, you are actually\nintroducing a potential race condition (not a data race, technically, but it can\nbe an awfully fine distinction):\n\n```rust\nlet value = tscounter.load(Ordering::SeqCst);\ntscounter.store(value + 1, Ordering::SeqCst);\n```\n\nYou can already see that the `AtomicUsize` API is a bit more complex, as it\nrequires you to specify an\n[ordering](https://doc.rust-lang.org/std/sync/atomic/enum.Ordering.html). (I\nwon't go into the details on ordering here, but suffice to say that if you don't\nknow what an ordering is, and probably even if you do, you should use\n`Ordering::SeqCst`.) The danger in this parallel version of the counter is that\nother threads might be running at the same time and they could cause our counter\nto get out of sync. For example, if we have two threads, then they might both\nexecute the \"load\" before either has a chance to execute the \"store\":\n\n```\nThread 1                                          Thread 2\nlet value = tscounter.load(Ordering::SeqCst);\n// value = X                                      let value = tscounter.load(Ordering::SeqCst);\n                                                  // value = X\ntscounter.store(value+1);                         tscounter.store(value+1);\n// tscounter = X+1                                // tscounter = X+1\n```\n\nNow even though we've had two increments, we'll only increase the counter by\none! Even though we've got no data race, this is still probably not the result\nwe wanted. The problem here is that the `Cell` API doesn't make clear the scope\nof a \"transaction\" -- that is, the set of reads/writes that should occur\natomically. In this case, we probably wanted the get/set to occur together.\n\nIn fact, when using the `Atomic` types, you very rarely want a plain `load` or\nplain `store`. You probably want the more complex operations. A counter, for\nexample, would use `fetch_add` to atomically load and increment the value in one\nstep. Compare-and-swap is another popular building block.\n\nA similar problem can arise when converting `RefCell` to `RwLock`, but it is\nsomewhat less likely, because the `RefCell` API does in fact have a notion of a\ntransaction: the scope of the handle returned by `borrow` or `borrow_mut`. So if\nyou convert each call to `borrow` to `read` (and `borrow_mut` to `write`),\nthings will mostly work fine in a parallel setting, but there can still be\nchanges in behavior. Consider using a `handle: RefCell<Vec<i32>>` like:\n\n```rust\nlet len = handle.borrow().len();\nfor i in 0 .. len {\n    let data = handle.borrow()[i];\n    println!(\"{}\", data);\n}\n```\n\nIn sequential code, we know that this loop is safe. But if we convert this to\nparallel code with an `RwLock`, we do not: this is because another thread could\ncome along and do `handle.write().unwrap().pop()`, and thus change the length of\nthe vector. In fact, even in *sequential* code, using very small borrow sections\nlike this is an anti-pattern: you ought to be enclosing the entire transaction\ntogether, like so:\n\n```rust\nlet vec = handle.borrow();\nlet len = vec.len();\nfor i in 0 .. len {\n    let data = vec[i];\n    println!(\"{}\", data);\n}\n```\n\nOr, even better, using an iterator instead of indexing:\n\n```rust\nlet vec = handle.borrow();\nfor data in vec {\n    println!(\"{}\", data);\n}\n```\n\nThere are several reasons to prefer one borrow over many. The most obvious is\nthat it is more efficient, since each borrow has to perform some safety checks.\nBut it's also more reliable: suppose we modified the loop above to not just\nprint things out, but also call into a helper function:\n\n```rust\nlet vec = handle.borrow();\nfor data in vec {\n    helper(...);\n}\n```\n\nAnd now suppose, independently, this helper fn evolved and had to pop something\noff of the vector:\n\n```rust\nfn helper(...) {\n    handle.borrow_mut().pop();\n}\n```\n\nUnder the old model, where we did lots of small borrows, this would yield\nprecisely the same error that we saw in parallel land using an `RwLock`: the\nlength would be out of sync and our indexing would fail (note that in neither\ncase would there be an actual *data race* and hence there would never be\nundefined behavior). But now that we use a single borrow, we'll see a borrow\nerror instead, which is much easier to diagnose, since it occurs at the point of\nthe `borrow_mut`, rather than downstream. Similarly, if we move to an `RwLock`,\nwe'll find that the code either deadlocks (if the write is on the same thread as\nthe read) or, if the write is on another thread, works just fine. Both of these\nare preferable to random failures in my experience.\n\n## But wait, isn't Rust supposed to free me from this kind of thinking?\n\nYou might think that Rust is supposed to mean that you don't have to think about\natomicity at all. In fact, if you avoid interior mutability (`Cell` and\n`RefCell` in a sequential setting, or `AtomicUsize`, `RwLock`, `Mutex`, et al.\nin parallel code), then this is true: the type system will basically guarantee\nthat you don't have to think about atomicity at all. But often there are times\nwhen you WANT threads to interleave in the ways I showed above.\n\nConsider for example when you are conducting a search in parallel, say to find\nthe shortest route. To avoid fruitless search, you might want to keep a cell\nwith the shortest route you've found thus far. This way, when you are searching\ndown some path that's already longer than this shortest route, you can just stop\nand avoid wasted effort. In sequential land, you might model this \"best result\"\nas a shared value like `Rc<Cell<usize>>` (here the `usize` represents the length\nof best path found so far); in parallel land, you'd use a `Arc<AtomicUsize>`.\n\n```rust\nfn search(path: &Path, cost_so_far: usize, best_cost: &AtomicUsize) {\n    if cost_so_far >= best_cost.load(Ordering::SeqCst) {\n        return;\n    }\n    // Using `fetch_min` to avoid a race condition, in case it changed since `load`.\n    best_cost.fetch_min(..., Ordering::SeqCst);\n}\n```\n\nNow in this case, we really WANT to see results from other threads interjected\ninto our execution!\n"
  },
  {
    "path": "LICENSE-APACHE",
    "content": "                              Apache License\n                        Version 2.0, January 2004\n                     http://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n   \"License\" shall mean the terms and conditions for use, reproduction,\n   and distribution as defined by Sections 1 through 9 of this document.\n\n   \"Licensor\" shall mean the copyright owner or entity authorized by\n   the copyright owner that is granting the License.\n\n   \"Legal Entity\" shall mean the union of the acting entity and all\n   other entities that control, are controlled by, or are under common\n   control with that entity. For the purposes of this definition,\n   \"control\" means (i) the power, direct or indirect, to cause the\n   direction or management of such entity, whether by contract or\n   otherwise, or (ii) ownership of fifty percent (50%) or more of the\n   outstanding shares, or (iii) beneficial ownership of such entity.\n\n   \"You\" (or \"Your\") shall mean an individual or Legal Entity\n   exercising permissions granted by this License.\n\n   \"Source\" form shall mean the preferred form for making modifications,\n   including but not limited to software source code, documentation\n   source, and configuration files.\n\n   \"Object\" form shall mean any form resulting from mechanical\n   transformation or translation of a Source form, including but\n   not limited to compiled object code, generated documentation,\n   and conversions to other media types.\n\n   \"Work\" shall mean the work of authorship, whether in Source or\n   Object form, made available under the License, as indicated by a\n   copyright notice that is included in or attached to the work\n   (an example is provided in the Appendix below).\n\n   \"Derivative Works\" shall mean any work, whether in Source or Object\n   form, that is based on (or derived from) the Work and for which the\n   editorial revisions, annotations, elaborations, or other modifications\n   represent, as a whole, an original work of authorship. For the purposes\n   of this License, Derivative Works shall not include works that remain\n   separable from, or merely link (or bind by name) to the interfaces of,\n   the Work and Derivative Works thereof.\n\n   \"Contribution\" shall mean any work of authorship, including\n   the original version of the Work and any modifications or additions\n   to that Work or Derivative Works thereof, that is intentionally\n   submitted to Licensor for inclusion in the Work by the copyright owner\n   or by an individual or Legal Entity authorized to submit on behalf of\n   the copyright owner. For the purposes of this definition, \"submitted\"\n   means any form of electronic, verbal, or written communication sent\n   to the Licensor or its representatives, including but not limited to\n   communication on electronic mailing lists, source code control systems,\n   and issue tracking systems that are managed by, or on behalf of, the\n   Licensor for the purpose of discussing and improving the Work, but\n   excluding communication that is conspicuously marked or otherwise\n   designated in writing by the copyright owner as \"Not a Contribution.\"\n\n   \"Contributor\" shall mean Licensor and any individual or Legal Entity\n   on behalf of whom a Contribution has been received by Licensor and\n   subsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   copyright license to reproduce, prepare Derivative Works of,\n   publicly display, publicly perform, sublicense, and distribute the\n   Work and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   (except as stated in this section) patent license to make, have made,\n   use, offer to sell, sell, import, and otherwise transfer the Work,\n   where such license applies only to those patent claims licensable\n   by such Contributor that are necessarily infringed by their\n   Contribution(s) alone or by combination of their Contribution(s)\n   with the Work to which such Contribution(s) was submitted. If You\n   institute patent litigation against any entity (including a\n   cross-claim or counterclaim in a lawsuit) alleging that the Work\n   or a Contribution incorporated within the Work constitutes direct\n   or contributory patent infringement, then any patent licenses\n   granted to You under this License for that Work shall terminate\n   as of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\n   Work or Derivative Works thereof in any medium, with or without\n   modifications, and in Source or Object form, provided that You\n   meet the following conditions:\n\n   (a) You must give any other recipients of the Work or\n       Derivative Works a copy of this License; and\n\n   (b) You must cause any modified files to carry prominent notices\n       stating that You changed the files; and\n\n   (c) You must retain, in the Source form of any Derivative Works\n       that You distribute, all copyright, patent, trademark, and\n       attribution notices from the Source form of the Work,\n       excluding those notices that do not pertain to any part of\n       the Derivative Works; and\n\n   (d) If the Work includes a \"NOTICE\" text file as part of its\n       distribution, then any Derivative Works that You distribute must\n       include a readable copy of the attribution notices contained\n       within such NOTICE file, excluding those notices that do not\n       pertain to any part of the Derivative Works, in at least one\n       of the following places: within a NOTICE text file distributed\n       as part of the Derivative Works; within the Source form or\n       documentation, if provided along with the Derivative Works; or,\n       within a display generated by the Derivative Works, if and\n       wherever such third-party notices normally appear. The contents\n       of the NOTICE file are for informational purposes only and\n       do not modify the License. You may add Your own attribution\n       notices within Derivative Works that You distribute, alongside\n       or as an addendum to the NOTICE text from the Work, provided\n       that such additional attribution notices cannot be construed\n       as modifying the License.\n\n   You may add Your own copyright statement to Your modifications and\n   may provide additional or different license terms and conditions\n   for use, reproduction, or distribution of Your modifications, or\n   for any such Derivative Works as a whole, provided Your use,\n   reproduction, and distribution of the Work otherwise complies with\n   the conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\n   any Contribution intentionally submitted for inclusion in the Work\n   by You to the Licensor shall be under the terms and conditions of\n   this License, without any additional terms or conditions.\n   Notwithstanding the above, nothing herein shall supersede or modify\n   the terms of any separate license agreement you may have executed\n   with Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\n   names, trademarks, service marks, or product names of the Licensor,\n   except as required for reasonable and customary use in describing the\n   origin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\n   agreed to in writing, Licensor provides the Work (and each\n   Contributor provides its Contributions) on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n   implied, including, without limitation, any warranties or conditions\n   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n   PARTICULAR PURPOSE. You are solely responsible for determining the\n   appropriateness of using or redistributing the Work and assume any\n   risks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\n   whether in tort (including negligence), contract, or otherwise,\n   unless required by applicable law (such as deliberate and grossly\n   negligent acts) or agreed to in writing, shall any Contributor be\n   liable to You for damages, including any direct, indirect, special,\n   incidental, or consequential damages of any character arising as a\n   result of this License or out of the use or inability to use the\n   Work (including but not limited to damages for loss of goodwill,\n   work stoppage, computer failure or malfunction, or any and all\n   other commercial damages or losses), even if such Contributor\n   has been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\n   the Work or Derivative Works thereof, You may choose to offer,\n   and charge a fee for, acceptance of support, warranty, indemnity,\n   or other liability obligations and/or rights consistent with this\n   License. However, in accepting such obligations, You may act only\n   on Your own behalf and on Your sole responsibility, not on behalf\n   of any other Contributor, and only if You agree to indemnify,\n   defend, and hold each Contributor harmless for any liability\n   incurred by, or claims asserted against, such Contributor by reason\n   of your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work.\n\n   To apply the Apache License to your work, attach the following\n   boilerplate notice, with the fields enclosed by brackets \"[]\"\n   replaced with your own identifying information. (Don't include\n   the brackets!)  The text should be enclosed in the appropriate\n   comment syntax for the file format. We also recommend that a\n   file or class name and description of purpose be included on the\n   same \"printed page\" as the copyright notice for easier\n   identification within third-party archives.\n\nCopyright [yyyy] [name of copyright owner]\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n"
  },
  {
    "path": "LICENSE-MIT",
    "content": "Copyright (c) 2010 The Rust Project Developers\n\nPermission is hereby granted, free of charge, to any\nperson obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the\nSoftware without restriction, including without\nlimitation the rights to use, copy, modify, merge,\npublish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software\nis furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice\nshall be included in all copies or substantial portions\nof the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF\nANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\nTO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\nPARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\nSHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR\nIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Rayon\n\n[![Rayon crate](https://img.shields.io/crates/v/rayon.svg)](https://crates.io/crates/rayon)\n[![Rayon documentation](https://docs.rs/rayon/badge.svg)](https://docs.rs/rayon)\n![minimum rustc 1.80](https://img.shields.io/badge/rustc-1.80+-red.svg)\n[![build status](https://github.com/rayon-rs/rayon/workflows/main/badge.svg)](https://github.com/rayon-rs/rayon/actions)\n\nRayon is a data-parallelism library for Rust. It is extremely\nlightweight and makes it easy to convert a sequential computation into\na parallel one. It also guarantees data-race freedom. (You may also\nenjoy [this blog post][blog] about Rayon, which gives more background\nand details about how it works, or [this video][video], from the Rust\nBelt Rust conference.) Rayon is\n[available on crates.io](https://crates.io/crates/rayon), and\n[API documentation is available on docs.rs](https://docs.rs/rayon).\n\n[blog]: https://smallcultfollowing.com/babysteps/blog/2015/12/18/rayon-data-parallelism-in-rust/\n[video]: https://www.youtube.com/watch?v=gof_OEv71Aw\n\n## Parallel iterators and more\n\nRayon makes it drop-dead simple to convert sequential iterators into\nparallel ones: usually, you just change your `foo.iter()` call into\n`foo.par_iter()`, and Rayon does the rest:\n\n```rust\nuse rayon::prelude::*;\nfn sum_of_squares(input: &[i32]) -> i32 {\n    input.par_iter() // <-- just change that!\n         .map(|&i| i * i)\n         .sum()\n}\n```\n\n[Parallel iterators] take care of deciding how to divide your data\ninto tasks; it will dynamically adapt for maximum performance. If you\nneed more flexibility than that, Rayon also offers the [join] and\n[scope] functions, which let you create parallel tasks on your own.\nFor even more control, you can create [custom thread pools] rather than\nusing Rayon's default, global thread pool.\n\n[Parallel iterators]: https://docs.rs/rayon/*/rayon/iter/index.html\n[join]: https://docs.rs/rayon/*/rayon/fn.join.html\n[scope]: https://docs.rs/rayon/*/rayon/fn.scope.html\n[custom thread pools]: https://docs.rs/rayon/*/rayon/struct.ThreadPool.html\n\n## No data races\n\nYou may have heard that parallel execution can produce all kinds of\ncrazy bugs. Well, rest easy. Rayon's APIs all guarantee **data-race\nfreedom**, which generally rules out most parallel bugs (though not\nall). In other words, **if your code compiles**, it typically does the\nsame thing it did before.\n\nFor the most, parallel iterators in particular are guaranteed to\nproduce the same results as their sequential counterparts. One caveat:\nIf your iterator has side effects (for example, sending methods to\nother threads through a [Rust channel] or writing to disk), those side\neffects may occur in a different order. Note also that, in some cases,\nparallel iterators offer alternative versions of the sequential\niterator methods that can have higher performance.\n\n[Rust channel]: https://doc.rust-lang.org/std/sync/mpsc/fn.channel.html\n\n## Using Rayon\n\n[Rayon is available on crates.io](https://crates.io/crates/rayon). The\nrecommended way to use it is to add a line into your Cargo.toml such\nas:\n\n```toml\n[dependencies]\nrayon = \"1.11\"\n```\n\nTo use the parallel iterator APIs, a number of traits have to be in\nscope. The easiest way to bring those things into scope is to use the\n[Rayon prelude](https://docs.rs/rayon/*/rayon/prelude/index.html). In\neach module where you would like to use the parallel iterator APIs,\njust add:\n\n```rust\nuse rayon::prelude::*;\n```\n\nRayon currently requires `rustc 1.80.0` or greater.\n\n### Usage with WebAssembly\n\nBy default, when building to WebAssembly, Rayon will treat it as any\nother platform without multithreading support and will fall back to\nsequential iteration. This allows existing code to compile and run\nsuccessfully with no changes necessary, but it will run slower as it\nwill only use a single CPU core.\n\nYou can build Rayon-based projects with proper multithreading support\nfor the Web, but you'll need an adapter and some project configuration\nto account for differences between WebAssembly threads and threads on\nthe other platforms.\n\nCheck out the\n[wasm-bindgen-rayon](https://github.com/RReverser/wasm-bindgen-rayon)\ndocs for more details.\n\n## Contribution\n\nRayon is an open source project! If you'd like to contribute to Rayon,\ncheck out\n[the list of \"help wanted\" issues](https://github.com/rayon-rs/rayon/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22).\nThese are all (or should be) issues that are suitable for getting\nstarted, and they generally include a detailed set of instructions for\nwhat to do. Please ask questions if anything is unclear! Also, check\nout the\n[Guide to Development](https://github.com/rayon-rs/rayon/wiki/Guide-to-Development)\npage on the wiki. Note that all code submitted in PRs to Rayon is\nassumed to\n[be licensed under Rayon's dual MIT/Apache 2.0 licensing](https://github.com/rayon-rs/rayon/blob/main/README.md#license).\n\n## Quick demo\n\nTo see Rayon in action, check out the `rayon-demo` directory, which\nincludes a number of demos of code using Rayon. For example, run this\ncommand to get a visualization of an N-body simulation. To see the\neffect of using Rayon, press `s` to run sequentially and `p` to run in\nparallel.\n\n```text\n> cd rayon-demo\n> cargo run --release -- nbody visualize\n```\n\nFor more information on demos, try:\n\n```text\n> cd rayon-demo\n> cargo run --release -- --help\n```\n\n## Other questions?\n\nSee [the Rayon FAQ][faq].\n\n[faq]: https://github.com/rayon-rs/rayon/blob/main/FAQ.md\n\n## License\n\nRayon is distributed under the terms of both the MIT license and the\nApache License (Version 2.0). See [LICENSE-APACHE](LICENSE-APACHE) and\n[LICENSE-MIT](LICENSE-MIT) for details. Opening a pull request is\nassumed to signal agreement with these licensing terms.\n"
  },
  {
    "path": "RELEASES.md",
    "content": "# Release rayon 1.11.0 / rayon-core 1.13.0 (2025-08-12)\n\n- The minimum supported `rustc` is now 1.80.\n- `iter::repeatn` has been renamed to `iter::repeat_n` to match the name\n  stabilized in the standard library. The old name still exists as a deprecated\n  function for compatibility.\n- Fixed a bug in `in_place_scope` when the default global registry uses the\n  current thread, like on WebAssembly without threading support.\n- `binary_heap::Iter` no longer requires a temporary allocation.\n- Relaxed trait bounds on many of the public structs.\n- Implemented `IntoParallelIterator for Box<[T]>` and its references.\n- Implemented `FromParallelIterator<_> for Box<str>` via `String`.\n\n# Release rayon 1.10.0 (2024-03-23)\n\n- The new methods `ParallelSlice::par_chunk_by` and\n  `ParallelSliceMut::par_chunk_by_mut` work like the slice methods `chunk_by`\n  and `chunk_by_mut` added in Rust 1.77.\n\n# Release rayon 1.9.0 (2024-02-27)\n\n- The new methods `IndexedParallelIterator::by_exponential_blocks` and\n  `by_uniform_blocks` allow processing items in smaller groups at a time.\n- The new `iter::walk_tree`, `walk_tree_prefix`, and `walk_tree_postfix`\n  functions enable custom parallel iteration over tree-like structures.\n- The new method `ParallelIterator::collect_vec_list` returns items as a linked\n  list of vectors, which is an efficient mode of parallel collection used by\n  many of the internal implementations of `collect`.\n- The new methods `ParallelSliceMut::par_split_inclusive_mut`,\n  `ParallelSlice::par_split_inclusive`, and\n  `ParallelString::par_split_inclusive` all work like a normal split but\n  keeping the separator as part of the left slice.\n- The new `ParallelString::par_split_ascii_whitespace` splits only on ASCII\n  whitespace, which is faster than including Unicode multi-byte whitespace.\n- `OsString` now implements `FromParallelIterator<_>` and `ParallelExtend<_>`\n  for a few item types similar to the standard `FromIterator` and `Extend`.\n- The internal `Pattern` trait for string methods is now implemented for\n  `[char; N]` and `&[char; N]`, matching any of the given characters.\n\n# Release rayon 1.8.1 / rayon-core 1.12.1 (2024-01-17)\n\n- The new `\"web_spin_lock\"` crate feature makes mutexes spin on the main\n  browser thread in WebAssembly, rather than suffer an error about forbidden\n  `atomics.wait` if they were to block in that context. Thanks @RReverser!\n\n# Release rayon 1.8.0 / rayon-core 1.12.0 (2023-09-20)\n\n- The minimum supported `rustc` is now 1.63.\n- Added `ThreadPoolBuilder::use_current_thread` to use the builder thread as\n  part of the new thread pool. That thread does not run the pool's main loop,\n  but it may participate in work-stealing if it yields to rayon in some way.\n- Implemented `FromParallelIterator<T>` for `Box<[T]>`, `Rc<[T]>`, and\n  `Arc<[T]>`, as well as `FromParallelIterator<Box<str>>` and\n  `ParallelExtend<Box<str>>` for `String`.\n- `ThreadPoolBuilder::build_scoped` now uses `std::thread::scope`.\n- The default number of threads is now determined using\n  `std::thread::available_parallelism` instead of the `num_cpus` crate.\n- The internal logging facility has been removed, reducing bloat for all users.\n- Many smaller performance tweaks and documentation updates.\n\n# Release rayon 1.7.0 / rayon-core 1.11.0 (2023-03-03)\n\n- The minimum supported `rustc` is now 1.59.\n- Added a fallback when threading is unsupported.\n- The new `ParallelIterator::take_any` and `skip_any` methods work like\n  unordered `IndexedParallelIterator::take` and `skip`, counting items in\n  whatever order they are visited in parallel.\n- The new `ParallelIterator::take_any_while` and `skip_any_while` methods work\n  like unordered `Iterator::take_while` and `skip_while`, which previously had\n  no parallel equivalent. The \"while\" condition may be satisfied from anywhere\n  in the parallel iterator, affecting all future items regardless of position.\n- The new `yield_now` and `yield_local` functions will cooperatively yield\n  execution to Rayon, either trying to execute pending work from the entire\n  pool or from just the local deques of the current thread, respectively.\n\n# Release rayon-core 1.10.2 (2023-01-22)\n\n- Fixed miri-reported UB for SharedReadOnly tags protected by a call.\n\n# Release rayon 1.6.1 (2022-12-09)\n\n- Simplified `par_bridge` to only pull one item at a time from the iterator,\n  without batching. Threads that are waiting for iterator items will now block\n  appropriately rather than spinning CPU. (Thanks @njaard!)\n- Added protection against recursion in `par_bridge`, so iterators that also\n  invoke rayon will not cause mutex recursion deadlocks.\n\n# Release rayon-core 1.10.1 (2022-11-18)\n\n- Fixed a race condition with threads going to sleep while a broadcast starts.\n\n# Release rayon 1.6.0 / rayon-core 1.10.0 (2022-11-18)\n\n- The minimum supported `rustc` is now 1.56.\n- The new `IndexedParallelIterator::fold_chunks` and `fold_chunks_with` methods\n  work like `ParallelIterator::fold` and `fold_with` with fixed-size chunks of\n  items. This may be useful for predictable batching performance, without the\n  allocation overhead of `IndexedParallelIterator::chunks`.\n- New \"broadcast\" methods run a given function on all threads in the pool.\n  These run at a sort of reduced priority after each thread has exhausted their\n  local work queue, but before they attempt work-stealing from other threads.\n  - The global `broadcast` function and `ThreadPool::broadcast` method will\n    block until completion, returning a `Vec` of all return values.\n  - The global `spawn_broadcast` function and methods on `ThreadPool`, `Scope`,\n    and `ScopeFifo` will run detached, without blocking the current thread.\n- Panicking methods now use `#[track_caller]` to report the caller's location.\n- Fixed a truncated length in `vec::Drain` when given an empty range.\n\n## Contributors\n\nThanks to all of the contributors for this release!\n\n- @cuviper\n- @idanmuze\n- @JoeyBF\n- @JustForFun88\n- @kianmeng\n- @kornelski\n- @ritchie46\n- @ryanrussell\n- @steffahn\n- @TheIronBorn\n- @willcrozi\n\n# Release rayon 1.5.3 (2022-05-13)\n\n- The new `ParallelSliceMut::par_sort_by_cached_key` is a stable sort that caches\n  the keys for each item -- a parallel version of `slice::sort_by_cached_key`.\n\n# Release rayon-core 1.9.3 (2022-05-13)\n\n- Fixed a use-after-free race in job notification.\n\n# Release rayon 1.5.2 / rayon-core 1.9.2 (2022-04-13)\n\n- The new `ParallelSlice::par_rchunks()` and `par_rchunks_exact()` iterate\n  slice chunks in reverse, aligned the against the end of the slice if the\n  length is not a perfect multiple of the chunk size. The new\n  `ParallelSliceMut::par_rchunks_mut()` and `par_rchunks_exact_mut()` are the\n  same for mutable slices.\n- The `ParallelIterator::try_*` methods now support `std::ops::ControlFlow` and\n  `std::task::Poll` items, mirroring the unstable `Try` implementations in the\n  standard library.\n- The `ParallelString` pattern-based methods now support `&[char]` patterns,\n  which match when any character in that slice is found in the string.\n- A soft limit is now enforced on the number of threads allowed in a single\n  thread pool, respecting internal bit limits that already existed. The current\n  maximum is publicly available from the new function `max_num_threads()`.\n- Fixed several Stacked Borrow and provenance issues found by `cargo miri`.\n\n## Contributors\n\nThanks to all of the contributors for this release!\n\n- @atouchet\n- @bluss\n- @cuviper\n- @fzyzcjy\n- @nyanzebra\n- @paolobarbolini\n- @RReverser\n- @saethlin\n\n# Release rayon 1.5.1 / rayon-core 1.9.1 (2021-05-18)\n\n- The new `in_place_scope` and `in_place_scope_fifo` are variations of `scope`\n  and `scope_fifo`, running the initial non-`Send` callback directly on the\n  current thread, rather than moving execution to the thread pool.\n- With Rust 1.51 or later, arrays now implement `IntoParallelIterator`.\n- New implementations of `FromParallelIterator` make it possible to `collect`\n  complicated nestings of items.\n  - `FromParallelIterator<(A, B)> for (FromA, FromB)` works like `unzip`.\n  - `FromParallelIterator<Either<L, R>> for (A, B)` works like `partition_map`.\n- Type inference now works better with parallel `Range` and `RangeInclusive`.\n- The implementation of `FromParallelIterator` and `ParallelExtend` for\n  `Vec<T>` now uses `MaybeUninit<T>` internally to avoid creating any\n  references to uninitialized data.\n- `ParallelBridge` fixed a bug with threads missing available work.\n\n## Contributors\n\nThanks to all of the contributors for this release!\n\n- @atouchet\n- @cuviper\n- @Hywan\n- @iRaiko\n- @Qwaz\n- @rocallahan\n\n# Release rayon 1.5.0 / rayon-core 1.9.0 (2020-10-21)\n\n- Update crossbeam dependencies.\n- The minimum supported `rustc` is now 1.36.\n\n## Contributors\n\nThanks to all of the contributors for this release!\n\n- @cuviper\n- @mbrubeck\n- @mrksu\n\n# Release rayon 1.4.1 (2020-09-29)\n\n- The new `flat_map_iter` and `flatten_iter` methods can be used to flatten\n  sequential iterators, which may perform better in cases that don't need the\n  nested parallelism of `flat_map` and `flatten`.\n- The new `par_drain` method is a parallel version of the standard `drain` for\n  collections, removing items while keeping the original capacity. Collections\n  that implement this through `ParallelDrainRange` support draining items from\n  arbitrary index ranges, while `ParallelDrainFull` always drains everything.\n- The new `positions` method finds all items that match the given predicate and\n  returns their indices in a new iterator.\n\n# Release rayon-core 1.8.1 (2020-09-17)\n\n- Fixed an overflow panic on high-contention workloads, for a counter that was\n  meant to simply wrap. This panic only occurred with debug assertions enabled,\n  and was much more likely on 32-bit targets.\n\n# Release rayon 1.4.0 / rayon-core 1.8.0 (2020-08-24)\n\n- Implemented a new thread scheduler, [RFC 5], which uses targeted wakeups for\n  new work and for notifications of completed stolen work, reducing wasteful\n  CPU usage in idle threads.\n- Implemented `IntoParallelIterator for Range<char>` and `RangeInclusive<char>`\n  with the same iteration semantics as Rust 1.45.\n- Relaxed the lifetime requirements of the initial `scope` closure.\n\n[RFC 5]: https://github.com/rayon-rs/rfcs/pull/5\n\n## Contributors\n\nThanks to all of the contributors for this release!\n\n- @CAD97\n- @cuviper\n- @kmaork\n- @nikomatsakis\n- @SuperFluffy\n\n\n# Release rayon 1.3.1 / rayon-core 1.7.1 (2020-06-15)\n\n- Fixed a use-after-free race in calls blocked between two rayon thread pools.\n- Collecting to an indexed `Vec` now drops any partial writes while unwinding,\n  rather than just leaking them. If dropping also panics, Rust will abort.\n  - Note: the old leaking behavior is considered _safe_, just not ideal.\n- The new `IndexedParallelIterator::step_by()` adapts an iterator to step\n  through items by the given count, like `Iterator::step_by()`.\n- The new `ParallelSlice::par_chunks_exact()` and mutable equivalent\n  `ParallelSliceMut::par_chunks_exact_mut()` ensure that the chunks always have\n  the exact length requested, leaving any remainder separate, like the slice\n  methods `chunks_exact()` and `chunks_exact_mut()`.\n\n## Contributors\n\nThanks to all of the contributors for this release!\n\n- @adrian5\n- @bluss\n- @cuviper\n- @FlyingCanoe\n- @GuillaumeGomez\n- @matthiasbeyer\n- @picoHz\n- @zesterer\n\n\n# Release rayon 1.3.0 / rayon-core 1.7.0 (2019-12-21)\n\n- Tuples up to length 12 now implement `IntoParallelIterator`, creating a\n  `MultiZip` iterator that produces items as similarly-shaped tuples.\n- The `--cfg=rayon_unstable` supporting code for `rayon-futures` is removed.\n- The minimum supported `rustc` is now 1.31.\n\n## Contributors\n\nThanks to all of the contributors for this release!\n\n- @cuviper\n- @c410-f3r\n- @silwol\n\n\n# Release rayon-futures 0.1.1 (2019-12-21)\n\n- `Send` bounds have been added for the `Item` and `Error` associated types on\n  all generic `F: Future` interfaces. While technically a breaking change, this\n  is a soundness fix, so we are not increasing the semantic version for this.\n- This crate is now deprecated, and the `--cfg=rayon_unstable` supporting code\n  will be removed in `rayon-core 1.7.0`. This only supported the now-obsolete\n  `Future` from `futures 0.1`, while support for `std::future::Future` is\n  expected to come directly in `rayon-core` -- although that is not ready yet.\n\n## Contributors\n\nThanks to all of the contributors for this release!\n\n- @cuviper\n- @kornelski\n- @jClaireCodesStuff\n- @jwass\n- @seanchen1991\n\n\n# Release rayon 1.2.1 / rayon-core 1.6.1 (2019-11-20)\n\n- Update crossbeam dependencies.\n- Add top-level doc links for the iterator traits.\n- Document that the iterator traits are not object safe.\n\n## Contributors\n\nThanks to all of the contributors for this release!\n\n- @cuviper\n- @dnaka91\n- @matklad\n- @nikomatsakis\n- @Qqwy\n- @vorner\n\n\n# Release rayon 1.2.0 / rayon-core 1.6.0 (2019-08-30)\n\n- The new `ParallelIterator::copied()` converts an iterator of references into\n  copied values, like `Iterator::copied()`.\n- `ParallelExtend` is now implemented for the unit `()`.\n- Internal updates were made to improve test determinism, reduce closure type\n  sizes, reduce task allocations, and update dependencies.\n- The minimum supported `rustc` is now 1.28.\n\n## Contributors\n\nThanks to all of the contributors for this release!\n\n- @Aaron1011\n- @cuviper\n- @ralfbiedert\n\n\n# Release rayon 1.1.0 / rayon-core 1.5.0 (2019-06-12)\n\n- FIFO spawns are now supported using the new `spawn_fifo()` and `scope_fifo()`\n  global functions, and their corresponding `ThreadPool` methods.\n  - Normally when tasks are queued on a thread, the most recent is processed\n    first (LIFO) while other threads will steal the oldest (FIFO). With FIFO\n    spawns, those tasks are processed locally in FIFO order too.\n  - Regular spawns and other tasks like `join` are not affected.\n  - The `breadth_first` configuration flag, which globally approximated this\n    effect, is now deprecated.\n  - For more design details, please see [RFC 1].\n- `ThreadPoolBuilder` can now take a custom `spawn_handler` to control how\n  threads will be created in the pool.\n  - `ThreadPoolBuilder::build_scoped()` uses this to create a scoped thread\n    pool, where the threads are able to use non-static data.\n  - This may also be used to support threading in exotic environments, like\n    WebAssembly, which don't support the normal `std::thread`.\n- `ParallelIterator` has 3 new methods: `find_map_any()`, `find_map_first()`,\n  and `find_map_last()`, like `Iterator::find_map()` with ordering constraints.\n- The new `ParallelIterator::panic_fuse()` makes a parallel iterator halt as soon\n  as possible if any of its threads panic. Otherwise, the panic state is not\n  usually noticed until the iterator joins its parallel tasks back together.\n- `IntoParallelIterator` is now implemented for integral `RangeInclusive`.\n- Several internal `Folder`s now have optimized `consume_iter` implementations.\n- `rayon_core::current_thread_index()` is now re-exported in `rayon`.\n- The minimum `rustc` is now 1.26, following the update policy defined in [RFC 3].\n\n## Contributors\n\nThanks to all of the contributors for this release!\n\n- @cuviper\n- @didroe\n- @GuillaumeGomez\n- @huonw\n- @janriemer\n- @kornelski\n- @nikomatsakis\n- @seanchen1991\n- @yegeun542\n\n[RFC 1]: https://github.com/rayon-rs/rfcs/blob/main/accepted/rfc0001-scope-scheduling.md\n[RFC 3]: https://github.com/rayon-rs/rfcs/blob/main/accepted/rfc0003-minimum-rustc.md\n\n\n# Release rayon 1.0.3 (2018-11-02)\n\n- `ParallelExtend` is now implemented for tuple pairs, enabling nested\n  `unzip()` and `partition_map()` operations.  For instance, `(A, (B, C))`\n  items can be unzipped into `(Vec<A>, (Vec<B>, Vec<C>))`.\n  - `ParallelExtend<(A, B)>` works like `unzip()`.\n  - `ParallelExtend<Either<A, B>>` works like `partition_map()`.\n- `ParallelIterator` now has a method `map_init()` which calls an `init`\n  function for a value to pair with items, like `map_with()` but dynamically\n  constructed.  That value type has no constraints, not even `Send` or `Sync`.\n  - The new `for_each_init()` is a variant of this for simple iteration.\n  - The new `try_for_each_init()` is a variant for fallible iteration.\n\n## Contributors\n\nThanks to all of the contributors for this release!\n\n- @cuviper\n- @dan-zheng\n- @dholbert\n- @ignatenkobrain\n- @mdonoughe\n\n\n# Release rayon 1.0.2 / rayon-core 1.4.1 (2018-07-17)\n\n- The `ParallelBridge` trait with method `par_bridge()` makes it possible to\n  use any `Send`able `Iterator` in parallel!\n  - This trait has been added to `rayon::prelude`.\n  - It automatically implements internal synchronization and queueing to\n    spread the `Item`s across the thread pool.  Iteration order is not\n    preserved by this adaptor.\n  - \"Native\" Rayon iterators like `par_iter()` should still be preferred when\n    possible for better efficiency.\n- `ParallelString` now has additional methods for parity with `std` string\n  iterators: `par_char_indices()`, `par_bytes()`, `par_encode_utf16()`,\n  `par_matches()`, and `par_match_indices()`.\n- `ParallelIterator` now has fallible methods `try_fold()`, `try_reduce()`,\n  and `try_for_each`, plus `*_with()` variants of each, for automatically\n  short-circuiting iterators on `None` or `Err` values.  These are inspired by\n  `Iterator::try_fold()` and `try_for_each()` that were stabilized in Rust 1.27.\n- `Range<i128>` and `Range<u128>` are now supported with Rust 1.26 and later.\n- Small improvements have been made to the documentation.\n- `rayon-core` now only depends on `rand` for testing.\n- Rayon tests now work on stable Rust.\n\n## Contributors\n\nThanks to all of the contributors for this release!\n\n- @AndyGauge\n- @cuviper\n- @ignatenkobrain\n- @LukasKalbertodt\n- @MajorBreakfast\n- @nikomatsakis\n- @paulkernfeld\n- @QuietMisdreavus\n\n\n# Release rayon 1.0.1 (2018-03-16)\n\n- Added more documentation for `rayon::iter::split()`.\n- Corrected links and typos in documentation.\n\n## Contributors\n\nThanks to all of the contributors for this release!\n\n- @cuviper\n- @HadrienG2\n- @matthiasbeyer\n- @nikomatsakis\n\n\n# Release rayon 1.0.0 / rayon-core 1.4.0 (2018-02-15)\n\n- `ParallelIterator` added the `update` method which applies a function to\n  mutable references, inspired by `itertools`.\n- `IndexedParallelIterator` added the `chunks` method which yields vectors of\n  consecutive items from the base iterator, inspired by `itertools`.\n- `String` now implements `FromParallelIterator<Cow<str>>` and\n  `ParallelExtend<Cow<str>>`, inspired by `std`.\n- `()` now implements `FromParallelIterator<()>`, inspired by `std`.\n- The new `ThreadPoolBuilder` replaces and deprecates `Configuration`.\n  - Errors from initialization now have the concrete `ThreadPoolBuildError`\n    type, rather than `Box<Error>`, and this type implements `Send` and `Sync`.\n  - `ThreadPool::new` is deprecated in favor of `ThreadPoolBuilder::build`.\n  - `initialize` is deprecated in favor of `ThreadPoolBuilder::build_global`.\n- Examples have been added to most of the parallel iterator methods.\n- A lot of the documentation has been reorganized and extended.\n\n## Breaking changes\n\n- Rayon now requires rustc 1.13 or greater.\n- `IndexedParallelIterator::len` and `ParallelIterator::opt_len` now operate on\n  `&self` instead of `&mut self`.\n- `IndexedParallelIterator::collect_into` is now `collect_into_vec`.\n- `IndexedParallelIterator::unzip_into` is now `unzip_into_vecs`.\n- Rayon no longer exports the deprecated `Configuration` and `initialize` from\n  rayon-core.\n\n## Contributors\n\nThanks to all of the contributors for this release!\n\n- @Bilkow\n- @cuviper\n- @Enet4\n- @ignatenkobrain\n- @iwillspeak\n- @jeehoonkang\n- @jwass\n- @Kerollmops\n- @KodrAus\n- @kornelski\n- @MaloJaffre\n- @nikomatsakis\n- @obv-mikhail\n- @oddg\n- @phimuemue\n- @stjepang\n- @tmccombs\n- bors[bot]\n\n\n# Release rayon 0.9.0 / rayon-core 1.3.0 / rayon-futures 0.1.0 (2017-11-09)\n\n- `Configuration` now has a `build` method.\n- `ParallelIterator` added `flatten` and `intersperse`, both inspired by\n  itertools.\n- `IndexedParallelIterator` added `interleave`, `interleave_shortest`, and\n  `zip_eq`, all inspired by itertools.\n- The new functions `iter::empty` and `once` create parallel iterators of\n  exactly zero or one item, like their `std` counterparts.\n- The new functions `iter::repeat` and `repeatn` create parallel iterators\n  repeating an item indefinitely or `n` times, respectively.\n- The new function `join_context` works like `join`, with an added `FnContext`\n  parameter that indicates whether the job was stolen.\n- `Either` (used by `ParallelIterator::partition_map`) is now re-exported from\n  the `either` crate, instead of defining our own type.\n  - `Either` also now implements `ParallelIterator`, `IndexedParallelIterator`,\n    and `ParallelExtend` when both of its `Left` and `Right` types do.\n- All public types now implement `Debug`.\n- Many of the parallel iterators now implement `Clone` where possible.\n- Much of the documentation has been extended. (but still could use more help!)\n- All rayon crates have improved metadata.\n- Rayon was evaluated in the Libz Blitz, leading to many of these improvements.\n- Rayon pull requests are now guarded by bors-ng.\n\n## Futures\n\nThe `spawn_future()` method has been refactored into its own `rayon-futures`\ncrate, now through a `ScopeFutureExt` trait for `ThreadPool` and `Scope`.  The\nsupporting `rayon-core` APIs are still gated by `--cfg rayon_unstable`.\n\n## Breaking changes\n\n- Two breaking changes have been made to `rayon-core`, but since they're fixing\n  soundness bugs, we are considering these _minor_ changes for semver.\n  - `Scope::spawn` now requires `Send` for the closure.\n  - `ThreadPool::install` now requires `Send` for the return value.\n- The `iter::internal` module has been renamed to `iter::plumbing`, to hopefully\n  indicate that while these are low-level details, they're not really internal\n  or private to rayon.  The contents of that module are needed for third-parties\n  to implement new parallel iterators, and we'll treat them with normal semver\n  stability guarantees.\n- The function `rayon::iter::split` is no longer re-exported as `rayon::split`.\n\n## Contributors\n\nThanks to all of the contributors for this release!\n\n- @AndyGauge\n- @ChristopherDavenport\n- @chrisvittal\n- @cuviper\n- @dns2utf8\n- @dtolnay\n- @frewsxcv\n- @gsquire\n- @Hittherhod\n- @jdr023\n- @laumann\n- @leodasvacas\n- @lvillani\n- @MajorBreakfast\n- @mamuleanu\n- @marmistrz\n- @mbrubeck\n- @mgattozzi\n- @nikomatsakis\n- @smt923\n- @stjepang\n- @tmccombs\n- @vishalsodani\n- bors[bot]\n\n\n# Release rayon 0.8.2 (2017-06-28)\n\n- `ParallelSliceMut` now has six parallel sorting methods with the same\n  variations as the standard library.\n  - `par_sort`, `par_sort_by`, and `par_sort_by_key` perform stable sorts in\n    parallel, using the default order, a custom comparator, or a key extraction\n    function, respectively.\n  - `par_sort_unstable`, `par_sort_unstable_by`, and `par_sort_unstable_by_key`\n    perform unstable sorts with the same comparison options.\n  - Thanks to @stjepang!\n\n\n# Release rayon 0.8.1 / rayon-core 1.2.0 (2017-06-14)\n\n- The following core APIs are being stabilized:\n  - `rayon::spawn()` -- spawns a task into the Rayon thread pool; as it\n    is contained in the global scope (rather than a user-created\n    scope), the task cannot capture anything from the current stack\n    frame.\n  - `ThreadPool::join()`, `ThreadPool::spawn()`, `ThreadPool::scope()`\n    -- convenience APIs for launching new work within a thread pool.\n- The various iterator adapters are now tagged with `#[must_use]`\n- Parallel iterators now offer a `for_each_with` adapter, similar to\n  `map_with`.\n- We are adopting a new approach to handling the remaining unstable\n  APIs (which primarily pertain to futures integration). As awlays,\n  unstable APIs are intended for experimentation, but do not come with\n  any promise of compatibility (in other words, we might change them\n  in arbitrary ways in any release). Previously, we designated such\n  APIs using a Cargo feature \"unstable\". Now, we are using a regular\n  `#[cfg]` flag. This means that to see the unstable APIs, you must do\n  `RUSTFLAGS='--cfg rayon_unstable' cargo build`. This is\n  intentionally inconvenient; in particular, if you are a library,\n  then your clients must also modify their environment, signaling\n  their agreement to instability.\n\n\n# Release rayon 0.8.0 / rayon-core 1.1.0 (2017-06-13)\n\n## Rayon 0.8.0\n\n- Added the `map_with` and `fold_with` combinators, which help for\n  passing along state (like channels) that cannot be shared between\n  threads but which can be cloned on each thread split.\n- Added the `while_some` combinator, which helps for writing short-circuiting iterators.\n- Added support for \"short-circuiting\" collection: e.g., collecting\n  from an iterator producing `Option<T>` or `Result<T, E>` into a\n  `Option<Collection<T>>` or `Result<Collection<T>, E>`.\n- Support `FromParallelIterator` for `Cow`.\n- Removed the deprecated weight APIs.\n- Simplified the parallel iterator trait hierarchy by removing the\n  `BoundedParallelIterator` and `ExactParallelIterator` traits,\n  which were not serving much purpose.\n- Improved documentation.\n- Added some missing `Send` impls.\n- Fixed some small bugs.\n\n## Rayon-core 1.1.0\n\n- We now have more documentation.\n- Renamed the (unstable) methods `spawn_async` and\n  `spawn_future_async` -- which spawn tasks that cannot hold\n  references -- to simply `spawn` and `spawn_future`, respectively.\n- We are now using the coco library for our deque.\n- Individual thread pools can now be configured in \"breadth-first\"\n  mode, which causes them to execute spawned tasks in the reverse\n  order that they used to.  In some specific scenarios, this can be a\n  win (though it is not generally the right choice).\n- Added top-level functions:\n  - `current_thread_index`, for querying the index of the current worker thread within\n    its thread pool (previously available as `thread_pool.current_thread_index()`);\n  - `current_thread_has_pending_tasks`, for querying whether the\n    current worker that has an empty task deque or not. This can be\n    useful when deciding whether to spawn a task.\n- The environment variables for controlling Rayon are now\n  `RAYON_NUM_THREADS` and `RAYON_LOG`. The older variables (e.g.,\n  `RAYON_RS_NUM_CPUS` are still supported but deprecated).\n\n## Rayon-demo\n\n- Added a new game-of-life benchmark.\n\n## Contributors\n\nThanks to the following contributors:\n\n- @ChristopherDavenport\n- @SuperFluffy\n- @antoinewdg\n- @crazymykl\n- @cuviper\n- @glandium\n- @julian-seward1\n- @leodasvacas\n- @leshow\n- @lilianmoraru\n- @mschmo\n- @nikomatsakis\n- @stjepang\n\n\n# Release rayon 0.7.1 / rayon-core 1.0.2 (2017-05-30)\n\nThis release is a targeted performance fix for #343, an issue where\nrayon threads could sometimes enter into a spin loop where they would\nbe unable to make progress until they are pre-empted.\n\n\n# Release rayon 0.7 / rayon-core 1.0 (2017-04-06)\n\nThis release marks the first step towards Rayon 1.0. **For best\nperformance, it is important that all Rayon users update to at least\nRayon 0.7.** This is because, as of Rayon 0.7, we have taken steps to\nensure that, no matter how many versions of rayon are actively in use,\nthere will only be a single global scheduler. This is achieved via the\n`rayon-core` crate, which is being released at version 1.0, and which\nencapsulates the core schedule APIs like `join()`. (Note: the\n`rayon-core` crate is, to some degree, an implementation detail, and\nnot intended to be imported directly; it's entire API surface is\nmirrored through the rayon crate.)\n\nWe have also done a lot of work reorganizing the API for Rayon 0.7 in\npreparation for 1.0. The names of iterator types have been changed and\nreorganized (but few users are expected to be naming those types\nexplicitly anyhow). In addition, a number of parallel iterator methods\nhave been adjusted to match those in the standard iterator traits more\nclosely. See the \"Breaking Changes\" section below for\ndetails.\n\nFinally, Rayon 0.7 includes a number of new features and new parallel\niterator methods. **As of this release, Rayon's parallel iterators\nhave officially reached parity with sequential iterators** -- that is,\nevery sequential iterator method that makes any sense in parallel is\nsupported in some capacity.\n\n### New features and methods\n\n- The internal `Producer` trait now features `fold_with`, which enables\n  better performance for some parallel iterators.\n- Strings now support `par_split()` and `par_split_whitespace()`.\n- The `Configuration` API is expanded and simplified:\n    - `num_threads(0)` no longer triggers an error\n    - you can now supply a closure to name the Rayon threads that get created\n      by using `Configuration::thread_name`.\n    - you can now inject code when Rayon threads start up and finish\n    - you can now set a custom panic handler to handle panics in various odd situations\n- Threadpools are now able to more gracefully put threads to sleep when not needed.\n- Parallel iterators now support `find_first()`, `find_last()`, `position_first()`,\n  and `position_last()`.\n- Parallel iterators now support `rev()`, which primarily affects subsequent calls\n  to `enumerate()`.\n- The `scope()` API is now considered stable (and part of `rayon-core`).\n- There is now a useful `rayon::split` function for creating custom\n  Rayon parallel iterators.\n- Parallel iterators now allow you to customize the min/max number of\n  items to be processed in a given thread. This mechanism replaces the\n  older `weight` mechanism, which is deprecated.\n- `sum()` and friends now use the standard `Sum` traits\n\n### Breaking changes\n\nIn the move towards 1.0, there have been a number of minor breaking changes:\n\n- Configuration setters like `Configuration::set_num_threads()` lost the `set_` prefix,\n  and hence become something like `Configuration::num_threads()`.\n- `Configuration` getters are removed\n- Iterator types have been shuffled around and exposed more consistently:\n    - combinator types live in `rayon::iter`, e.g. `rayon::iter::Filter`\n    - iterators over various types live in a module named after their type,\n      e.g. `rayon::slice::Windows`\n- When doing a `sum()` or `product()`, type annotations are needed for the result\n  since it is now possible to have the resulting sum be of a type other than the value\n  you are iterating over (this mirrors sequential iterators).\n\n### Experimental features\n\nExperimental features require the use of the `unstable` feature. Their\nAPIs may change or disappear entirely in future releases (even minor\nreleases) and hence they should be avoided for production code.\n\n- We now have (unstable) support for futures integration. You can use\n  `Scope::spawn_future` or `rayon::spawn_future_async()`.\n- There is now a `rayon::spawn_async()` function for using the Rayon\n  thread pool to run tasks that do not have references to the stack.\n\n### Contributors\n\nThanks to the following people for their contributions to this release:\n\n- @Aaronepower\n- @ChristopherDavenport\n- @bluss\n- @cuviper\n- @froydnj\n- @gaurikholkar\n- @hniksic\n- @leodasvacas\n- @leshow\n- @martinhath\n- @mbrubeck\n- @nikomatsakis\n- @pegomes\n- @schuster\n- @torkleyy\n\n\n# Release 0.6 (2016-12-21)\n\nThis release includes a lot of progress towards the goal of parity\nwith the sequential iterator API, though there are still a few methods\nthat are not yet complete. If you'd like to help with that effort,\n[check out the milestone](https://github.com/rayon-rs/rayon/issues?q=is%3Aopen+is%3Aissue+milestone%3A%22Parity+with+the+%60Iterator%60+trait%22)\nto see the remaining issues.\n\n**Announcement:** @cuviper has been added as a collaborator to the\nRayon repository for all of his outstanding work on Rayon, which\nincludes both internal refactoring and helping to shape the public\nAPI. Thanks @cuviper! Keep it up.\n\n- We now support `collect()` and not just `collect_with()`.\n  You can use `collect()` to build a number of collections,\n  including vectors, maps, and sets. Moreover, when building a vector\n  with `collect()`, you are no longer limited to exact parallel iterators.\n  Thanks @nikomatsakis, @cuviper!\n- We now support `skip()` and `take()` on parallel iterators.\n  Thanks @martinhath!\n- **Breaking change:** We now match the sequential APIs for `min()` and `max()`.\n  We also support `min_by_key()` and `max_by_key()`. Thanks @tapeinosyne!\n- **Breaking change:** The `mul()` method is now renamed to `product()`,\n  to match sequential iterators. Thanks @jonathandturner!\n- We now support parallel iterator over ranges on `u64` values. Thanks @cuviper!\n- We now offer a `par_chars()` method on strings for iterating over characters\n  in parallel. Thanks @cuviper!\n- We now have new demos: a traveling salesman problem solver as well as matrix\n  multiplication. Thanks @nikomatsakis, @edre!\n- We are now documenting our minimum rustc requirement (currently\n  v1.12.0).  We will attempt to maintain compatibility with rustc\n  stable v1.12.0 as long as it remains convenient, but if new features\n  are stabilized or added that would be helpful to Rayon, or there are\n  bug fixes that we need, we will bump to the most recent rustc. Thanks @cuviper!\n- The `reduce()` functionality now has better inlining.\n  Thanks @bluss!\n- The `join()` function now has some documentation. Thanks @gsquire!\n- The project source has now been fully run through rustfmt.\n  Thanks @ChristopherDavenport!\n- Exposed helper methods for accessing the current thread index.\n  Thanks @bholley!\n\n\n# Release 0.5 (2016-11-04)\n\n- **Breaking change:** The `reduce` method has been vastly\n  simplified, and `reduce_with_identity` has been deprecated.\n- **Breaking change:** The `fold` method has been changed. It used to\n  always reduce the values, but now instead it is a combinator that\n  returns a parallel iterator which can itself be reduced. See the\n  docs for more information.\n- The following parallel iterator combinators are now available (thanks @cuviper!):\n  - `find_any()`: similar to `find` on a sequential iterator,\n    but doesn't necessarily return the *first* matching item\n  - `position_any()`: similar to `position` on a sequential iterator,\n    but doesn't necessarily return the index of *first* matching item\n  - `any()`, `all()`: just like their sequential counterparts\n- The `count()` combinator is now available for parallel iterators.\n- We now build with older versions of rustc again (thanks @durango!),\n  as we removed a stray semicolon from `thread_local!`.\n- Various improvements to the (unstable) `scope()` API implementation.\n\n\n# Release 0.4.3 (2016-10-25)\n\n- Parallel iterators now offer an adaptive weight scheme,\n  which means that explicit weights should no longer\n  be necessary in most cases! Thanks @cuviper!\n  - We are considering removing weights or changing the weight mechanism\n    before 1.0. Examples of scenarios where you still need weights even\n    with this adaptive mechanism would be great. Join the discussion\n    at <https://github.com/rayon-rs/rayon/issues/111>.\n- New (unstable) scoped threads API, see `rayon::scope` for details.\n  - You will need to supply the [cargo feature] `unstable`.\n- The various demos and benchmarks have been consolidated into one\n  program, `rayon-demo`.\n- Optimizations in Rayon's inner workings. Thanks @emilio!\n- Update `num_cpus` to 1.0. Thanks @jamwt!\n- Various internal cleanup in the implementation and typo fixes.\n  Thanks @cuviper, @Eh2406, and @spacejam!\n\n[cargo feature]: https://doc.rust-lang.org/cargo/reference/features.html#the-features-section\n\n\n# Release 0.4.2 (2016-09-15)\n\n- Updated crates.io metadata.\n\n\n# Release 0.4.1 (2016-09-14)\n\n- New `chain` combinator for parallel iterators.\n- `Option`, `Result`, as well as many more collection types now have\n  parallel iterators.\n- New mergesort demo.\n- Misc fixes.\n\nThanks to @cuviper, @edre, @jdanford, @frewsxcv for their contributions!\n\n\n# Release 0.4 (2016-05-16)\n\n- Make use of latest versions of catch-panic and various fixes to panic propagation.\n- Add new prime sieve demo.\n- Add `cloned()` and `inspect()` combinators.\n- Misc fixes for Rust RFC 1214.\n\nThanks to @areilb1, @Amanieu, @SharplEr, and @cuviper for their contributions!\n\n\n# Release 0.3 (2016-02-23)\n\n- Expanded `par_iter` APIs now available:\n  - `into_par_iter` is now supported on vectors (taking ownership of the elements)\n- Panic handling is much improved:\n  - if you use the Nightly feature, experimental panic recovery is available\n  - otherwise, panics propagate out and poision the workpool\n- New `Configuration` object to control number of threads and other details\n- New demos and benchmarks\n  - try `cargo run --release -- visualize` in `demo/nbody` :)\n    - Note: a nightly compiler is required for this demo due to the\n      use of the `+=` syntax\n\nThanks to @bjz, @cuviper, @Amanieu, and @willi-kappler for their contributions!\n\n\n# Release 0.2 and earlier\n\nNo release notes were being kept at this time.\n"
  },
  {
    "path": "ci/alt-core/Cargo.toml",
    "content": "[package]\nedition = \"2018\"\nname = \"alt-core\"\nversion = \"0.0.0\"\nauthors = [\"Josh Stone <cuviper@gmail.com>\"]\nlinks = \"rayon-core\"\nbuild = \"build.rs\"\npublish = false\n\n[dependencies]\n"
  },
  {
    "path": "ci/alt-core/build.rs",
    "content": "fn main() {}\n"
  },
  {
    "path": "ci/alt-core/src/lib.rs",
    "content": ""
  },
  {
    "path": "ci/highlander/Cargo.toml",
    "content": "[package]\nauthors = [\"Josh Stone <cuviper@gmail.com>\"]\nedition = \"2018\"\nname = \"highlander\"\ndescription = \"There Can Be Only One\"\nversion = \"0.0.0\"\npublish = false\n\n[dependencies]\n\n[dependencies.alt-core]\noptional = false\npath = \"../alt-core\"\n\n[dependencies.rayon-core]\noptional = false\npath = \"../../rayon-core\"\n"
  },
  {
    "path": "ci/highlander/src/main.rs",
    "content": "fn main() {}\n"
  },
  {
    "path": "ci/highlander.sh",
    "content": "#!/bin/bash\n\nDIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\necho \"INFO: There Can Be Only One!\" >&2\n\nif cargo build --manifest-path \"$DIR/highlander/Cargo.toml\"; then\n    echo \"ERROR: we built with multiple rayon-core!\" >&2\n    exit 1\nfi\n\necho \"PASS: using multiple rayon-core failed.\" >&2\n"
  },
  {
    "path": "rayon-core/Cargo.toml",
    "content": "[package]\nname = \"rayon-core\"\nversion = \"1.13.0\"\ndescription = \"Core APIs for Rayon\"\ndocumentation = \"https://docs.rs/rayon-core/\"\nlinks = \"rayon-core\"\nbuild = \"build.rs\"\n\ncategories.workspace = true\nedition.workspace = true\nkeywords.workspace = true\nlicense.workspace = true\nreadme.workspace = true\nrepository.workspace = true\nrust-version.workspace = true\n\n[features]\n# This feature switches to a spin-lock implementation on the browser's\n# main thread to avoid the forbidden `atomics.wait`.\n#\n# Only useful on the `wasm32-unknown-unknown` target.\nweb_spin_lock = [\"dep:wasm_sync\"]\n\n[dependencies]\ncrossbeam-deque.workspace = true\ncrossbeam-utils.workspace = true\nwasm_sync = { workspace = true, optional = true }\n\n[dev-dependencies]\nrand.workspace = true\nrand_xorshift.workspace = true\nscoped-tls.workspace = true\n\n[target.'cfg(unix)'.dev-dependencies]\nlibc.workspace = true\n"
  },
  {
    "path": "rayon-core/LICENSE-APACHE",
    "content": "                              Apache License\n                        Version 2.0, January 2004\n                     http://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n   \"License\" shall mean the terms and conditions for use, reproduction,\n   and distribution as defined by Sections 1 through 9 of this document.\n\n   \"Licensor\" shall mean the copyright owner or entity authorized by\n   the copyright owner that is granting the License.\n\n   \"Legal Entity\" shall mean the union of the acting entity and all\n   other entities that control, are controlled by, or are under common\n   control with that entity. For the purposes of this definition,\n   \"control\" means (i) the power, direct or indirect, to cause the\n   direction or management of such entity, whether by contract or\n   otherwise, or (ii) ownership of fifty percent (50%) or more of the\n   outstanding shares, or (iii) beneficial ownership of such entity.\n\n   \"You\" (or \"Your\") shall mean an individual or Legal Entity\n   exercising permissions granted by this License.\n\n   \"Source\" form shall mean the preferred form for making modifications,\n   including but not limited to software source code, documentation\n   source, and configuration files.\n\n   \"Object\" form shall mean any form resulting from mechanical\n   transformation or translation of a Source form, including but\n   not limited to compiled object code, generated documentation,\n   and conversions to other media types.\n\n   \"Work\" shall mean the work of authorship, whether in Source or\n   Object form, made available under the License, as indicated by a\n   copyright notice that is included in or attached to the work\n   (an example is provided in the Appendix below).\n\n   \"Derivative Works\" shall mean any work, whether in Source or Object\n   form, that is based on (or derived from) the Work and for which the\n   editorial revisions, annotations, elaborations, or other modifications\n   represent, as a whole, an original work of authorship. For the purposes\n   of this License, Derivative Works shall not include works that remain\n   separable from, or merely link (or bind by name) to the interfaces of,\n   the Work and Derivative Works thereof.\n\n   \"Contribution\" shall mean any work of authorship, including\n   the original version of the Work and any modifications or additions\n   to that Work or Derivative Works thereof, that is intentionally\n   submitted to Licensor for inclusion in the Work by the copyright owner\n   or by an individual or Legal Entity authorized to submit on behalf of\n   the copyright owner. For the purposes of this definition, \"submitted\"\n   means any form of electronic, verbal, or written communication sent\n   to the Licensor or its representatives, including but not limited to\n   communication on electronic mailing lists, source code control systems,\n   and issue tracking systems that are managed by, or on behalf of, the\n   Licensor for the purpose of discussing and improving the Work, but\n   excluding communication that is conspicuously marked or otherwise\n   designated in writing by the copyright owner as \"Not a Contribution.\"\n\n   \"Contributor\" shall mean Licensor and any individual or Legal Entity\n   on behalf of whom a Contribution has been received by Licensor and\n   subsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   copyright license to reproduce, prepare Derivative Works of,\n   publicly display, publicly perform, sublicense, and distribute the\n   Work and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   (except as stated in this section) patent license to make, have made,\n   use, offer to sell, sell, import, and otherwise transfer the Work,\n   where such license applies only to those patent claims licensable\n   by such Contributor that are necessarily infringed by their\n   Contribution(s) alone or by combination of their Contribution(s)\n   with the Work to which such Contribution(s) was submitted. If You\n   institute patent litigation against any entity (including a\n   cross-claim or counterclaim in a lawsuit) alleging that the Work\n   or a Contribution incorporated within the Work constitutes direct\n   or contributory patent infringement, then any patent licenses\n   granted to You under this License for that Work shall terminate\n   as of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\n   Work or Derivative Works thereof in any medium, with or without\n   modifications, and in Source or Object form, provided that You\n   meet the following conditions:\n\n   (a) You must give any other recipients of the Work or\n       Derivative Works a copy of this License; and\n\n   (b) You must cause any modified files to carry prominent notices\n       stating that You changed the files; and\n\n   (c) You must retain, in the Source form of any Derivative Works\n       that You distribute, all copyright, patent, trademark, and\n       attribution notices from the Source form of the Work,\n       excluding those notices that do not pertain to any part of\n       the Derivative Works; and\n\n   (d) If the Work includes a \"NOTICE\" text file as part of its\n       distribution, then any Derivative Works that You distribute must\n       include a readable copy of the attribution notices contained\n       within such NOTICE file, excluding those notices that do not\n       pertain to any part of the Derivative Works, in at least one\n       of the following places: within a NOTICE text file distributed\n       as part of the Derivative Works; within the Source form or\n       documentation, if provided along with the Derivative Works; or,\n       within a display generated by the Derivative Works, if and\n       wherever such third-party notices normally appear. The contents\n       of the NOTICE file are for informational purposes only and\n       do not modify the License. You may add Your own attribution\n       notices within Derivative Works that You distribute, alongside\n       or as an addendum to the NOTICE text from the Work, provided\n       that such additional attribution notices cannot be construed\n       as modifying the License.\n\n   You may add Your own copyright statement to Your modifications and\n   may provide additional or different license terms and conditions\n   for use, reproduction, or distribution of Your modifications, or\n   for any such Derivative Works as a whole, provided Your use,\n   reproduction, and distribution of the Work otherwise complies with\n   the conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\n   any Contribution intentionally submitted for inclusion in the Work\n   by You to the Licensor shall be under the terms and conditions of\n   this License, without any additional terms or conditions.\n   Notwithstanding the above, nothing herein shall supersede or modify\n   the terms of any separate license agreement you may have executed\n   with Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\n   names, trademarks, service marks, or product names of the Licensor,\n   except as required for reasonable and customary use in describing the\n   origin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\n   agreed to in writing, Licensor provides the Work (and each\n   Contributor provides its Contributions) on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n   implied, including, without limitation, any warranties or conditions\n   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n   PARTICULAR PURPOSE. You are solely responsible for determining the\n   appropriateness of using or redistributing the Work and assume any\n   risks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\n   whether in tort (including negligence), contract, or otherwise,\n   unless required by applicable law (such as deliberate and grossly\n   negligent acts) or agreed to in writing, shall any Contributor be\n   liable to You for damages, including any direct, indirect, special,\n   incidental, or consequential damages of any character arising as a\n   result of this License or out of the use or inability to use the\n   Work (including but not limited to damages for loss of goodwill,\n   work stoppage, computer failure or malfunction, or any and all\n   other commercial damages or losses), even if such Contributor\n   has been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\n   the Work or Derivative Works thereof, You may choose to offer,\n   and charge a fee for, acceptance of support, warranty, indemnity,\n   or other liability obligations and/or rights consistent with this\n   License. However, in accepting such obligations, You may act only\n   on Your own behalf and on Your sole responsibility, not on behalf\n   of any other Contributor, and only if You agree to indemnify,\n   defend, and hold each Contributor harmless for any liability\n   incurred by, or claims asserted against, such Contributor by reason\n   of your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work.\n\n   To apply the Apache License to your work, attach the following\n   boilerplate notice, with the fields enclosed by brackets \"[]\"\n   replaced with your own identifying information. (Don't include\n   the brackets!)  The text should be enclosed in the appropriate\n   comment syntax for the file format. We also recommend that a\n   file or class name and description of purpose be included on the\n   same \"printed page\" as the copyright notice for easier\n   identification within third-party archives.\n\nCopyright [yyyy] [name of copyright owner]\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n"
  },
  {
    "path": "rayon-core/LICENSE-MIT",
    "content": "Copyright (c) 2010 The Rust Project Developers\n\nPermission is hereby granted, free of charge, to any\nperson obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the\nSoftware without restriction, including without\nlimitation the rights to use, copy, modify, merge,\npublish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software\nis furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice\nshall be included in all copies or substantial portions\nof the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF\nANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\nTO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\nPARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\nSHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR\nIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "rayon-core/README.md",
    "content": "Rayon-core represents the \"core, stable\" APIs of Rayon: join, scope, and so forth, as well as the ability to create custom thread pools with ThreadPool.\n\nMaybe worth mentioning: users are not necessarily intended to directly access rayon-core; all its APIs are mirrored in the rayon crate. To that end, the examples in the docs use rayon::join and so forth rather than rayon_core::join.\n\nrayon-core aims to never, or almost never, have a breaking change to its API, because each revision of rayon-core also houses the global thread pool (and hence if you have two simultaneous versions of rayon-core, you have two thread pools).\n\nPlease see [Rayon Docs] for details about using Rayon.\n\n[Rayon Docs]: https://docs.rs/rayon/\n\nRayon-core currently requires `rustc 1.80.0` or greater.\n"
  },
  {
    "path": "rayon-core/build.rs",
    "content": "// We need a build script to use `link = \"rayon-core\"`.  But we're not\n// *actually* linking to anything, just making sure that we're the only\n// rayon-core in use.\nfn main() {\n    // we don't need to rebuild for anything else\n    println!(\"cargo:rerun-if-changed=build.rs\");\n}\n"
  },
  {
    "path": "rayon-core/src/broadcast/mod.rs",
    "content": "use crate::job::{ArcJob, StackJob};\nuse crate::latch::{CountLatch, LatchRef};\nuse crate::registry::{Registry, WorkerThread};\nuse std::fmt;\nuse std::marker::PhantomData;\nuse std::sync::Arc;\n\nmod test;\n\n/// Executes `op` within every thread in the current thread pool. If this is\n/// called from a non-Rayon thread, it will execute in the global thread pool.\n/// Any attempts to use `join`, `scope`, or parallel iterators will then operate\n/// within that thread pool. When the call has completed on each thread, returns\n/// a vector containing all of their return values.\n///\n/// For more information, see the [`ThreadPool::broadcast()`] method.\n///\n/// [`ThreadPool::broadcast()`]: crate::ThreadPool::broadcast()\npub fn broadcast<OP, R>(op: OP) -> Vec<R>\nwhere\n    OP: Fn(BroadcastContext<'_>) -> R + Sync,\n    R: Send,\n{\n    // We assert that current registry has not terminated.\n    unsafe { broadcast_in(op, &Registry::current()) }\n}\n\n/// Spawns an asynchronous task on every thread in this thread pool. This task\n/// will run in the implicit, global scope, which means that it may outlast the\n/// current stack frame -- therefore, it cannot capture any references onto the\n/// stack (you will likely need a `move` closure).\n///\n/// For more information, see the [`ThreadPool::spawn_broadcast()`] method.\n///\n/// [`ThreadPool::spawn_broadcast()`]: crate::ThreadPool::spawn_broadcast()\npub fn spawn_broadcast<OP>(op: OP)\nwhere\n    OP: Fn(BroadcastContext<'_>) + Send + Sync + 'static,\n{\n    // We assert that current registry has not terminated.\n    unsafe { spawn_broadcast_in(op, &Registry::current()) }\n}\n\n/// Provides context to a closure called by `broadcast`.\npub struct BroadcastContext<'a> {\n    worker: &'a WorkerThread,\n\n    /// Make sure to prevent auto-traits like `Send` and `Sync`.\n    _marker: PhantomData<&'a mut dyn Fn()>,\n}\n\nimpl<'a> BroadcastContext<'a> {\n    pub(super) fn with<R>(f: impl FnOnce(BroadcastContext<'_>) -> R) -> R {\n        let worker_thread = WorkerThread::current();\n        assert!(!worker_thread.is_null());\n        f(BroadcastContext {\n            worker: unsafe { &*worker_thread },\n            _marker: PhantomData,\n        })\n    }\n\n    /// Our index amongst the broadcast threads (ranges from `0..self.num_threads()`).\n    #[inline]\n    pub fn index(&self) -> usize {\n        self.worker.index()\n    }\n\n    /// The number of threads receiving the broadcast in the thread pool.\n    ///\n    /// # Future compatibility note\n    ///\n    /// Future versions of Rayon might vary the number of threads over time, but\n    /// this method will always return the number of threads which are actually\n    /// receiving your particular `broadcast` call.\n    #[inline]\n    pub fn num_threads(&self) -> usize {\n        self.worker.registry().num_threads()\n    }\n}\n\nimpl<'a> fmt::Debug for BroadcastContext<'a> {\n    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt.debug_struct(\"BroadcastContext\")\n            .field(\"index\", &self.index())\n            .field(\"num_threads\", &self.num_threads())\n            .field(\"pool_id\", &self.worker.registry().id())\n            .finish()\n    }\n}\n\n/// Execute `op` on every thread in the pool. It will be executed on each\n/// thread when they have nothing else to do locally, before they try to\n/// steal work from other threads. This function will not return until all\n/// threads have completed the `op`.\n///\n/// Unsafe because `registry` must not yet have terminated.\npub(super) unsafe fn broadcast_in<OP, R>(op: OP, registry: &Arc<Registry>) -> Vec<R>\nwhere\n    OP: Fn(BroadcastContext<'_>) -> R + Sync,\n    R: Send,\n{\n    let f = move |injected: bool| {\n        debug_assert!(injected);\n        BroadcastContext::with(&op)\n    };\n\n    let n_threads = registry.num_threads();\n    let current_thread = WorkerThread::current().as_ref();\n    let latch = CountLatch::with_count(n_threads, current_thread);\n    let jobs: Vec<_> = (0..n_threads)\n        .map(|_| StackJob::new(&f, LatchRef::new(&latch)))\n        .collect();\n    let job_refs = jobs.iter().map(|job| job.as_job_ref());\n\n    registry.inject_broadcast(job_refs);\n\n    // Wait for all jobs to complete, then collect the results, maybe propagating a panic.\n    latch.wait(current_thread);\n    jobs.into_iter().map(|job| job.into_result()).collect()\n}\n\n/// Execute `op` on every thread in the pool. It will be executed on each\n/// thread when they have nothing else to do locally, before they try to\n/// steal work from other threads. This function returns immediately after\n/// injecting the jobs.\n///\n/// Unsafe because `registry` must not yet have terminated.\npub(super) unsafe fn spawn_broadcast_in<OP>(op: OP, registry: &Arc<Registry>)\nwhere\n    OP: Fn(BroadcastContext<'_>) + Send + Sync + 'static,\n{\n    let job = ArcJob::new({\n        let registry = Arc::clone(registry);\n        move || {\n            registry.catch_unwind(|| BroadcastContext::with(&op));\n            registry.terminate(); // (*) permit registry to terminate now\n        }\n    });\n\n    let n_threads = registry.num_threads();\n    let job_refs = (0..n_threads).map(|_| {\n        // Ensure that registry cannot terminate until this job has executed\n        // on each thread. This ref is decremented at the (*) above.\n        registry.increment_terminate_count();\n\n        ArcJob::as_static_job_ref(&job)\n    });\n\n    registry.inject_broadcast(job_refs);\n}\n"
  },
  {
    "path": "rayon-core/src/broadcast/test.rs",
    "content": "#![cfg(test)]\n\nuse crate::ThreadPoolBuilder;\nuse std::sync::atomic::{AtomicUsize, Ordering};\nuse std::sync::mpsc::channel;\nuse std::sync::Arc;\nuse std::{thread, time};\n\n#[test]\nfn broadcast_global() {\n    let v = crate::broadcast(|ctx| ctx.index());\n    assert!(v.into_iter().eq(0..crate::current_num_threads()));\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn spawn_broadcast_global() {\n    let (tx, rx) = channel();\n    crate::spawn_broadcast(move |ctx| tx.send(ctx.index()).unwrap());\n\n    let mut v: Vec<_> = rx.into_iter().collect();\n    v.sort_unstable();\n    assert!(v.into_iter().eq(0..crate::current_num_threads()));\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn broadcast_pool() {\n    let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap();\n    let v = pool.broadcast(|ctx| ctx.index());\n    assert!(v.into_iter().eq(0..7));\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn spawn_broadcast_pool() {\n    let (tx, rx) = channel();\n    let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap();\n    pool.spawn_broadcast(move |ctx| tx.send(ctx.index()).unwrap());\n\n    let mut v: Vec<_> = rx.into_iter().collect();\n    v.sort_unstable();\n    assert!(v.into_iter().eq(0..7));\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn broadcast_self() {\n    let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap();\n    let v = pool.install(|| crate::broadcast(|ctx| ctx.index()));\n    assert!(v.into_iter().eq(0..7));\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn spawn_broadcast_self() {\n    let (tx, rx) = channel();\n    let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap();\n    pool.spawn(|| crate::spawn_broadcast(move |ctx| tx.send(ctx.index()).unwrap()));\n\n    let mut v: Vec<_> = rx.into_iter().collect();\n    v.sort_unstable();\n    assert!(v.into_iter().eq(0..7));\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn broadcast_mutual() {\n    let count = AtomicUsize::new(0);\n    let pool1 = ThreadPoolBuilder::new().num_threads(3).build().unwrap();\n    let pool2 = ThreadPoolBuilder::new().num_threads(7).build().unwrap();\n    pool1.install(|| {\n        pool2.broadcast(|_| {\n            pool1.broadcast(|_| {\n                count.fetch_add(1, Ordering::Relaxed);\n            })\n        })\n    });\n    assert_eq!(count.into_inner(), 3 * 7);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn spawn_broadcast_mutual() {\n    let (tx, rx) = channel();\n    let pool1 = Arc::new(ThreadPoolBuilder::new().num_threads(3).build().unwrap());\n    let pool2 = ThreadPoolBuilder::new().num_threads(7).build().unwrap();\n    pool1.spawn({\n        let pool1 = Arc::clone(&pool1);\n        move || {\n            pool2.spawn_broadcast(move |_| {\n                let tx = tx.clone();\n                pool1.spawn_broadcast(move |_| tx.send(()).unwrap())\n            })\n        }\n    });\n    assert_eq!(rx.into_iter().count(), 3 * 7);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn broadcast_mutual_sleepy() {\n    let count = AtomicUsize::new(0);\n    let pool1 = ThreadPoolBuilder::new().num_threads(3).build().unwrap();\n    let pool2 = ThreadPoolBuilder::new().num_threads(7).build().unwrap();\n    pool1.install(|| {\n        thread::sleep(time::Duration::from_secs(1));\n        pool2.broadcast(|_| {\n            thread::sleep(time::Duration::from_secs(1));\n            pool1.broadcast(|_| {\n                thread::sleep(time::Duration::from_millis(100));\n                count.fetch_add(1, Ordering::Relaxed);\n            })\n        })\n    });\n    assert_eq!(count.into_inner(), 3 * 7);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn spawn_broadcast_mutual_sleepy() {\n    let (tx, rx) = channel();\n    let pool1 = Arc::new(ThreadPoolBuilder::new().num_threads(3).build().unwrap());\n    let pool2 = ThreadPoolBuilder::new().num_threads(7).build().unwrap();\n    pool1.spawn({\n        let pool1 = Arc::clone(&pool1);\n        move || {\n            thread::sleep(time::Duration::from_secs(1));\n            pool2.spawn_broadcast(move |_| {\n                let tx = tx.clone();\n                thread::sleep(time::Duration::from_secs(1));\n                pool1.spawn_broadcast(move |_| {\n                    thread::sleep(time::Duration::from_millis(100));\n                    tx.send(()).unwrap();\n                })\n            })\n        }\n    });\n    assert_eq!(rx.into_iter().count(), 3 * 7);\n}\n\n#[test]\n#[cfg_attr(not(panic = \"unwind\"), ignore)]\nfn broadcast_panic_one() {\n    let count = AtomicUsize::new(0);\n    let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap();\n    let result = crate::unwind::halt_unwinding(|| {\n        pool.broadcast(|ctx| {\n            count.fetch_add(1, Ordering::Relaxed);\n            if ctx.index() == 3 {\n                panic!(\"Hello, world!\");\n            }\n        })\n    });\n    assert_eq!(count.into_inner(), 7);\n    assert!(result.is_err(), \"broadcast panic should propagate!\");\n}\n\n#[test]\n#[cfg_attr(not(panic = \"unwind\"), ignore)]\nfn spawn_broadcast_panic_one() {\n    let (tx, rx) = channel();\n    let (panic_tx, panic_rx) = channel();\n    let pool = ThreadPoolBuilder::new()\n        .num_threads(7)\n        .panic_handler(move |e| panic_tx.send(e).unwrap())\n        .build()\n        .unwrap();\n    pool.spawn_broadcast(move |ctx| {\n        tx.send(()).unwrap();\n        if ctx.index() == 3 {\n            panic!(\"Hello, world!\");\n        }\n    });\n    drop(pool); // including panic_tx\n    assert_eq!(rx.into_iter().count(), 7);\n    assert_eq!(panic_rx.into_iter().count(), 1);\n}\n\n#[test]\n#[cfg_attr(not(panic = \"unwind\"), ignore)]\nfn broadcast_panic_many() {\n    let count = AtomicUsize::new(0);\n    let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap();\n    let result = crate::unwind::halt_unwinding(|| {\n        pool.broadcast(|ctx| {\n            count.fetch_add(1, Ordering::Relaxed);\n            if ctx.index() % 2 == 0 {\n                panic!(\"Hello, world!\");\n            }\n        })\n    });\n    assert_eq!(count.into_inner(), 7);\n    assert!(result.is_err(), \"broadcast panic should propagate!\");\n}\n\n#[test]\n#[cfg_attr(not(panic = \"unwind\"), ignore)]\nfn spawn_broadcast_panic_many() {\n    let (tx, rx) = channel();\n    let (panic_tx, panic_rx) = channel();\n    let pool = ThreadPoolBuilder::new()\n        .num_threads(7)\n        .panic_handler(move |e| panic_tx.send(e).unwrap())\n        .build()\n        .unwrap();\n    pool.spawn_broadcast(move |ctx| {\n        tx.send(()).unwrap();\n        if ctx.index() % 2 == 0 {\n            panic!(\"Hello, world!\");\n        }\n    });\n    drop(pool); // including panic_tx\n    assert_eq!(rx.into_iter().count(), 7);\n    assert_eq!(panic_rx.into_iter().count(), 4);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn broadcast_sleep_race() {\n    let test_duration = time::Duration::from_secs(1);\n    let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap();\n    let start = time::Instant::now();\n    while start.elapsed() < test_duration {\n        pool.broadcast(|ctx| {\n            // A slight spread of sleep duration increases the chance that one\n            // of the threads will race in the pool's idle sleep afterward.\n            thread::sleep(time::Duration::from_micros(ctx.index() as u64));\n        });\n    }\n}\n\n#[test]\nfn broadcast_after_spawn_broadcast() {\n    let (tx, rx) = channel();\n\n    // Queue a non-blocking spawn_broadcast.\n    crate::spawn_broadcast(move |ctx| tx.send(ctx.index()).unwrap());\n\n    // This blocking broadcast runs after all prior broadcasts.\n    crate::broadcast(|_| {});\n\n    // The spawn_broadcast **must** have run by now on all threads.\n    let mut v: Vec<_> = rx.try_iter().collect();\n    v.sort_unstable();\n    assert!(v.into_iter().eq(0..crate::current_num_threads()));\n}\n\n#[test]\nfn broadcast_after_spawn() {\n    let (tx, rx) = channel();\n\n    // Queue a regular spawn on a thread-local deque.\n    crate::registry::in_worker(move |_, _| {\n        crate::spawn(move || tx.send(22).unwrap());\n    });\n\n    // Broadcast runs after the local deque is empty.\n    crate::broadcast(|_| {});\n\n    // The spawn **must** have run by now.\n    assert_eq!(22, rx.try_recv().unwrap());\n}\n"
  },
  {
    "path": "rayon-core/src/compile_fail/mod.rs",
    "content": "// These modules contain `compile_fail` doc tests.\nmod quicksort_race1;\nmod quicksort_race2;\nmod quicksort_race3;\nmod rc_return;\nmod rc_upvar;\nmod scope_join_bad;\n"
  },
  {
    "path": "rayon-core/src/compile_fail/quicksort_race1.rs",
    "content": "/*! ```compile_fail,E0524\n\nfn quick_sort<T:PartialOrd+Send>(v: &mut [T]) {\n    if v.len() <= 1 {\n        return;\n    }\n\n    let mid = partition(v);\n    let (lo, _hi) = v.split_at_mut(mid);\n    rayon_core::join(|| quick_sort(lo), || quick_sort(lo)); //~ ERROR\n}\n\nfn partition<T:PartialOrd+Send>(v: &mut [T]) -> usize {\n    let pivot = v.len() - 1;\n    let mut i = 0;\n    for j in 0..pivot {\n        if v[j] <= v[pivot] {\n            v.swap(i, j);\n            i += 1;\n        }\n    }\n    v.swap(i, pivot);\n    i\n}\n\nfn main() { }\n\n``` */\n"
  },
  {
    "path": "rayon-core/src/compile_fail/quicksort_race2.rs",
    "content": "/*! ```compile_fail,E0500\n\nfn quick_sort<T:PartialOrd+Send>(v: &mut [T]) {\n    if v.len() <= 1 {\n        return;\n    }\n\n    let mid = partition(v);\n    let (lo, _hi) = v.split_at_mut(mid);\n    rayon_core::join(|| quick_sort(lo), || quick_sort(v)); //~ ERROR\n}\n\nfn partition<T:PartialOrd+Send>(v: &mut [T]) -> usize {\n    let pivot = v.len() - 1;\n    let mut i = 0;\n    for j in 0..pivot {\n        if v[j] <= v[pivot] {\n            v.swap(i, j);\n            i += 1;\n        }\n    }\n    v.swap(i, pivot);\n    i\n}\n\nfn main() { }\n\n``` */\n"
  },
  {
    "path": "rayon-core/src/compile_fail/quicksort_race3.rs",
    "content": "/*! ```compile_fail,E0524\n\nfn quick_sort<T:PartialOrd+Send>(v: &mut [T]) {\n    if v.len() <= 1 {\n        return;\n    }\n\n    let mid = partition(v);\n    let (_lo, hi) = v.split_at_mut(mid);\n    rayon_core::join(|| quick_sort(hi), || quick_sort(hi)); //~ ERROR\n}\n\nfn partition<T:PartialOrd+Send>(v: &mut [T]) -> usize {\n    let pivot = v.len() - 1;\n    let mut i = 0;\n    for j in 0..pivot {\n        if v[j] <= v[pivot] {\n            v.swap(i, j);\n            i += 1;\n        }\n    }\n    v.swap(i, pivot);\n    i\n}\n\nfn main() { }\n\n``` */\n"
  },
  {
    "path": "rayon-core/src/compile_fail/rc_return.rs",
    "content": "/** ```compile_fail,E0277\n\nuse std::rc::Rc;\n\nrayon_core::join(|| Rc::new(22), || ()); //~ ERROR\n\n``` */\nmod left {}\n\n/** ```compile_fail,E0277\n\nuse std::rc::Rc;\n\nrayon_core::join(|| (), || Rc::new(23)); //~ ERROR\n\n``` */\nmod right {}\n"
  },
  {
    "path": "rayon-core/src/compile_fail/rc_upvar.rs",
    "content": "/*! ```compile_fail,E0277\n\nuse std::rc::Rc;\n\nlet r = Rc::new(22);\nrayon_core::join(|| r.clone(), || r.clone());\n//~^ ERROR\n\n``` */\n"
  },
  {
    "path": "rayon-core/src/compile_fail/scope_join_bad.rs",
    "content": "/*! ```compile_fail,E0373\n\nfn bad_scope<F>(f: F)\n    where F: FnOnce(&i32) + Send,\n{\n    rayon_core::scope(|s| {\n        let x = 22;\n        s.spawn(|_| f(&x)); //~ ERROR `x` does not live long enough\n    });\n}\n\nfn good_scope<F>(f: F)\n    where F: FnOnce(&i32) + Send,\n{\n    let x = 22;\n    rayon_core::scope(|s| {\n        s.spawn(|_| f(&x));\n    });\n}\n\nfn main() {\n}\n\n``` */\n"
  },
  {
    "path": "rayon-core/src/job.rs",
    "content": "use crate::latch::Latch;\nuse crate::unwind;\nuse crossbeam_deque::{Injector, Steal};\nuse std::any::Any;\nuse std::cell::UnsafeCell;\nuse std::mem;\nuse std::sync::Arc;\n\npub(super) enum JobResult<T> {\n    None,\n    Ok(T),\n    Panic(Box<dyn Any + Send>),\n}\n\n/// A `Job` is used to advertise work for other threads that they may\n/// want to steal. In accordance with time honored tradition, jobs are\n/// arranged in a deque, so that thieves can take from the top of the\n/// deque while the main worker manages the bottom of the deque. This\n/// deque is managed by the `thread_pool` module.\npub(super) trait Job {\n    /// Unsafe: this may be called from a different thread than the one\n    /// which scheduled the job, so the implementer must ensure the\n    /// appropriate traits are met, whether `Send`, `Sync`, or both.\n    unsafe fn execute(this: *const ());\n}\n\n/// Effectively a Job trait object. Each JobRef **must** be executed\n/// exactly once, or else data may leak.\n///\n/// Internally, we store the job's data in a `*const ()` pointer.  The\n/// true type is something like `*const StackJob<...>`, but we hide\n/// it. We also carry the \"execute fn\" from the `Job` trait.\npub(super) struct JobRef {\n    pointer: *const (),\n    execute_fn: unsafe fn(*const ()),\n}\n\nunsafe impl Send for JobRef {}\nunsafe impl Sync for JobRef {}\n\nimpl JobRef {\n    /// Unsafe: caller asserts that `data` will remain valid until the\n    /// job is executed.\n    pub(super) unsafe fn new<T>(data: *const T) -> JobRef\n    where\n        T: Job,\n    {\n        // erase types:\n        JobRef {\n            pointer: data as *const (),\n            execute_fn: <T as Job>::execute,\n        }\n    }\n\n    /// Returns an opaque handle that can be saved and compared,\n    /// without making `JobRef` itself `Copy + Eq`.\n    #[inline]\n    pub(super) fn id(&self) -> impl Eq {\n        (self.pointer, self.execute_fn)\n    }\n\n    #[inline]\n    pub(super) unsafe fn execute(self) {\n        (self.execute_fn)(self.pointer)\n    }\n}\n\n/// A job that will be owned by a stack slot. This means that when it\n/// executes it need not free any heap data, the cleanup occurs when\n/// the stack frame is later popped.  The function parameter indicates\n/// `true` if the job was stolen -- executed on a different thread.\npub(super) struct StackJob<L, F, R>\nwhere\n    L: Latch + Sync,\n    F: FnOnce(bool) -> R + Send,\n    R: Send,\n{\n    pub(super) latch: L,\n    func: UnsafeCell<Option<F>>,\n    result: UnsafeCell<JobResult<R>>,\n}\n\nimpl<L, F, R> StackJob<L, F, R>\nwhere\n    L: Latch + Sync,\n    F: FnOnce(bool) -> R + Send,\n    R: Send,\n{\n    pub(super) fn new(func: F, latch: L) -> StackJob<L, F, R> {\n        StackJob {\n            latch,\n            func: UnsafeCell::new(Some(func)),\n            result: UnsafeCell::new(JobResult::None),\n        }\n    }\n\n    pub(super) unsafe fn as_job_ref(&self) -> JobRef {\n        JobRef::new(self)\n    }\n\n    pub(super) unsafe fn run_inline(self, stolen: bool) -> R {\n        self.func.into_inner().unwrap()(stolen)\n    }\n\n    pub(super) unsafe fn into_result(self) -> R {\n        self.result.into_inner().into_return_value()\n    }\n}\n\nimpl<L, F, R> Job for StackJob<L, F, R>\nwhere\n    L: Latch + Sync,\n    F: FnOnce(bool) -> R + Send,\n    R: Send,\n{\n    unsafe fn execute(this: *const ()) {\n        let this = &*(this as *const Self);\n        let abort = unwind::AbortIfPanic;\n        let func = (*this.func.get()).take().unwrap();\n        (*this.result.get()) = JobResult::call(func);\n        Latch::set(&this.latch);\n        mem::forget(abort);\n    }\n}\n\n/// Represents a job stored in the heap. Used to implement\n/// `scope`. Unlike `StackJob`, when executed, `HeapJob` simply\n/// invokes a closure, which then triggers the appropriate logic to\n/// signal that the job executed.\n///\n/// (Probably `StackJob` should be refactored in a similar fashion.)\npub(super) struct HeapJob<BODY>\nwhere\n    BODY: FnOnce() + Send,\n{\n    job: BODY,\n}\n\nimpl<BODY> HeapJob<BODY>\nwhere\n    BODY: FnOnce() + Send,\n{\n    pub(super) fn new(job: BODY) -> Box<Self> {\n        Box::new(HeapJob { job })\n    }\n\n    /// Creates a `JobRef` from this job -- note that this hides all\n    /// lifetimes, so it is up to you to ensure that this JobRef\n    /// doesn't outlive any data that it closes over.\n    pub(super) unsafe fn into_job_ref(self: Box<Self>) -> JobRef {\n        JobRef::new(Box::into_raw(self))\n    }\n\n    /// Creates a static `JobRef` from this job.\n    pub(super) fn into_static_job_ref(self: Box<Self>) -> JobRef\n    where\n        BODY: 'static,\n    {\n        unsafe { self.into_job_ref() }\n    }\n}\n\nimpl<BODY> Job for HeapJob<BODY>\nwhere\n    BODY: FnOnce() + Send,\n{\n    unsafe fn execute(this: *const ()) {\n        let this = Box::from_raw(this as *mut Self);\n        (this.job)();\n    }\n}\n\n/// Represents a job stored in an `Arc` -- like `HeapJob`, but may\n/// be turned into multiple `JobRef`s and called multiple times.\npub(super) struct ArcJob<BODY>\nwhere\n    BODY: Fn() + Send + Sync,\n{\n    job: BODY,\n}\n\nimpl<BODY> ArcJob<BODY>\nwhere\n    BODY: Fn() + Send + Sync,\n{\n    pub(super) fn new(job: BODY) -> Arc<Self> {\n        Arc::new(ArcJob { job })\n    }\n\n    /// Creates a `JobRef` from this job -- note that this hides all\n    /// lifetimes, so it is up to you to ensure that this JobRef\n    /// doesn't outlive any data that it closes over.\n    pub(super) unsafe fn as_job_ref(this: &Arc<Self>) -> JobRef {\n        JobRef::new(Arc::into_raw(Arc::clone(this)))\n    }\n\n    /// Creates a static `JobRef` from this job.\n    pub(super) fn as_static_job_ref(this: &Arc<Self>) -> JobRef\n    where\n        BODY: 'static,\n    {\n        unsafe { Self::as_job_ref(this) }\n    }\n}\n\nimpl<BODY> Job for ArcJob<BODY>\nwhere\n    BODY: Fn() + Send + Sync,\n{\n    unsafe fn execute(this: *const ()) {\n        let this = Arc::from_raw(this as *mut Self);\n        (this.job)();\n    }\n}\n\nimpl<T> JobResult<T> {\n    fn call(func: impl FnOnce(bool) -> T) -> Self {\n        match unwind::halt_unwinding(|| func(true)) {\n            Ok(x) => JobResult::Ok(x),\n            Err(x) => JobResult::Panic(x),\n        }\n    }\n\n    /// Convert the `JobResult` for a job that has finished (and hence\n    /// its JobResult is populated) into its return value.\n    ///\n    /// NB. This will panic if the job panicked.\n    pub(super) fn into_return_value(self) -> T {\n        match self {\n            JobResult::None => unreachable!(),\n            JobResult::Ok(x) => x,\n            JobResult::Panic(x) => unwind::resume_unwinding(x),\n        }\n    }\n}\n\n/// Indirect queue to provide FIFO job priority.\npub(super) struct JobFifo {\n    inner: Injector<JobRef>,\n}\n\nimpl JobFifo {\n    pub(super) fn new() -> Self {\n        JobFifo {\n            inner: Injector::new(),\n        }\n    }\n\n    pub(super) unsafe fn push(&self, job_ref: JobRef) -> JobRef {\n        // A little indirection ensures that spawns are always prioritized in FIFO order.  The\n        // jobs in a thread's deque may be popped from the back (LIFO) or stolen from the front\n        // (FIFO), but either way they will end up popping from the front of this queue.\n        self.inner.push(job_ref);\n        JobRef::new(self)\n    }\n}\n\nimpl Job for JobFifo {\n    unsafe fn execute(this: *const ()) {\n        // We \"execute\" a queue by executing its first job, FIFO.\n        let this = &*(this as *const Self);\n        loop {\n            match this.inner.steal() {\n                Steal::Success(job_ref) => break job_ref.execute(),\n                Steal::Empty => panic!(\"FIFO is empty\"),\n                Steal::Retry => {}\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "rayon-core/src/join/mod.rs",
    "content": "use crate::job::StackJob;\nuse crate::latch::SpinLatch;\nuse crate::registry::{self, WorkerThread};\nuse crate::unwind;\nuse std::any::Any;\n\nuse crate::FnContext;\n\n#[cfg(test)]\nmod test;\n\n/// Takes two closures and *potentially* runs them in parallel. It\n/// returns a pair of the results from those closures.\n///\n/// Conceptually, calling `join()` is similar to spawning two threads,\n/// one executing each of the two closures. However, the\n/// implementation is quite different and incurs very low\n/// overhead. The underlying technique is called \"work stealing\": the\n/// Rayon runtime uses a fixed pool of worker threads and attempts to\n/// only execute code in parallel when there are idle CPUs to handle\n/// it.\n///\n/// When `join` is called from outside the thread pool, the calling\n/// thread will block while the closures execute in the pool.  When\n/// `join` is called within the pool, the calling thread still actively\n/// participates in the thread pool. It will begin by executing closure\n/// A (on the current thread). While it is doing that, it will advertise\n/// closure B as being available for other threads to execute. Once closure A\n/// has completed, the current thread will try to execute closure B;\n/// if however closure B has been stolen, then it will look for other work\n/// while waiting for the thief to fully execute closure B. (This is the\n/// typical work-stealing strategy).\n///\n/// # Examples\n///\n/// This example uses join to perform a quick-sort (note this is not a\n/// particularly optimized implementation: if you **actually** want to\n/// sort for real, you should prefer [the `par_sort` method] offered\n/// by Rayon).\n///\n/// [the `par_sort` method]: ../rayon/slice/trait.ParallelSliceMut.html#method.par_sort\n///\n/// ```rust\n/// # use rayon_core as rayon;\n/// let mut v = vec![5, 1, 8, 22, 0, 44];\n/// quick_sort(&mut v);\n/// assert_eq!(v, vec![0, 1, 5, 8, 22, 44]);\n///\n/// fn quick_sort<T:PartialOrd+Send>(v: &mut [T]) {\n///    if v.len() > 1 {\n///        let mid = partition(v);\n///        let (lo, hi) = v.split_at_mut(mid);\n///        rayon::join(|| quick_sort(lo),\n///                    || quick_sort(hi));\n///    }\n/// }\n///\n/// // Partition rearranges all items `<=` to the pivot\n/// // item (arbitrary selected to be the last item in the slice)\n/// // to the first half of the slice. It then returns the\n/// // \"dividing point\" where the pivot is placed.\n/// fn partition<T:PartialOrd+Send>(v: &mut [T]) -> usize {\n///     let pivot = v.len() - 1;\n///     let mut i = 0;\n///     for j in 0..pivot {\n///         if v[j] <= v[pivot] {\n///             v.swap(i, j);\n///             i += 1;\n///         }\n///     }\n///     v.swap(i, pivot);\n///     i\n/// }\n/// ```\n///\n/// # Warning about blocking I/O\n///\n/// The assumption is that the closures given to `join()` are\n/// CPU-bound tasks that do not perform I/O or other blocking\n/// operations. If you do perform I/O, and that I/O should block\n/// (e.g., waiting for a network request), the overall performance may\n/// be poor.  Moreover, if you cause one closure to be blocked waiting\n/// on another (for example, using a channel), that could lead to a\n/// deadlock.\n///\n/// # Panics\n///\n/// No matter what happens, both closures will always be executed.  If\n/// a single closure panics, whether it be the first or second\n/// closure, that panic will be propagated and hence `join()` will\n/// panic with the same panic value. If both closures panic, `join()`\n/// will panic with the panic value from the first closure.\npub fn join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)\nwhere\n    A: FnOnce() -> RA + Send,\n    B: FnOnce() -> RB + Send,\n    RA: Send,\n    RB: Send,\n{\n    #[inline]\n    fn call<R>(f: impl FnOnce() -> R) -> impl FnOnce(FnContext) -> R {\n        move |_| f()\n    }\n\n    join_context(call(oper_a), call(oper_b))\n}\n\n/// Identical to `join`, except that the closures have a parameter\n/// that provides context for the way the closure has been called,\n/// especially indicating whether they're executing on a different\n/// thread than where `join_context` was called.  This will occur if\n/// the second job is stolen by a different thread, or if\n/// `join_context` was called from outside the thread pool to begin\n/// with.\npub fn join_context<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)\nwhere\n    A: FnOnce(FnContext) -> RA + Send,\n    B: FnOnce(FnContext) -> RB + Send,\n    RA: Send,\n    RB: Send,\n{\n    #[inline]\n    fn call_a<R>(f: impl FnOnce(FnContext) -> R, injected: bool) -> impl FnOnce() -> R {\n        move || f(FnContext::new(injected))\n    }\n\n    #[inline]\n    fn call_b<R>(f: impl FnOnce(FnContext) -> R) -> impl FnOnce(bool) -> R {\n        move |migrated| f(FnContext::new(migrated))\n    }\n\n    registry::in_worker(|worker_thread, injected| unsafe {\n        // Create virtual wrapper for task b; this all has to be\n        // done here so that the stack frame can keep it all live\n        // long enough.\n        let job_b = StackJob::new(call_b(oper_b), SpinLatch::new(worker_thread));\n        let job_b_ref = job_b.as_job_ref();\n        let job_b_id = job_b_ref.id();\n        worker_thread.push(job_b_ref);\n\n        // Execute task a; hopefully b gets stolen in the meantime.\n        let status_a = unwind::halt_unwinding(call_a(oper_a, injected));\n        let result_a = match status_a {\n            Ok(v) => v,\n            Err(err) => join_recover_from_panic(worker_thread, &job_b.latch, err),\n        };\n\n        // Now that task A has finished, try to pop job B from the\n        // local stack.  It may already have been popped by job A; it\n        // may also have been stolen. There may also be some tasks\n        // pushed on top of it in the stack, and we will have to pop\n        // those off to get to it.\n        while !job_b.latch.probe() {\n            let Some(job) = worker_thread.take_local_job() else {\n                // Local deque is empty. Time to steal from other\n                // threads.\n                worker_thread.wait_until(&job_b.latch);\n                debug_assert!(job_b.latch.probe());\n                break;\n            };\n            if job_b_id == job.id() {\n                // Found it! Let's run it.\n                //\n                // Note that this could panic, but it's ok if we unwind here.\n                let result_b = job_b.run_inline(injected);\n                return (result_a, result_b);\n            }\n            worker_thread.execute(job);\n        }\n\n        (result_a, job_b.into_result())\n    })\n}\n\n/// If job A panics, we still cannot return until we are sure that job\n/// B is complete. This is because it may contain references into the\n/// enclosing stack frame(s).\n#[cold] // cold path\nunsafe fn join_recover_from_panic(\n    worker_thread: &WorkerThread,\n    job_b_latch: &SpinLatch<'_>,\n    err: Box<dyn Any + Send>,\n) -> ! {\n    worker_thread.wait_until(job_b_latch);\n    unwind::resume_unwinding(err)\n}\n"
  },
  {
    "path": "rayon-core/src/join/test.rs",
    "content": "//! Tests for the join code.\n\nuse super::*;\nuse crate::ThreadPoolBuilder;\nuse rand::distr::StandardUniform;\nuse rand::{Rng, SeedableRng};\nuse rand_xorshift::XorShiftRng;\n\nfn quick_sort<T: PartialOrd + Send>(v: &mut [T]) {\n    if v.len() <= 1 {\n        return;\n    }\n\n    let mid = partition(v);\n    let (lo, hi) = v.split_at_mut(mid);\n    join(|| quick_sort(lo), || quick_sort(hi));\n}\n\nfn partition<T: PartialOrd + Send>(v: &mut [T]) -> usize {\n    let pivot = v.len() - 1;\n    let mut i = 0;\n    for j in 0..pivot {\n        if v[j] <= v[pivot] {\n            v.swap(i, j);\n            i += 1;\n        }\n    }\n    v.swap(i, pivot);\n    i\n}\n\nfn seeded_rng() -> XorShiftRng {\n    let mut seed = <XorShiftRng as SeedableRng>::Seed::default();\n    (0..).zip(seed.as_mut()).for_each(|(i, x)| *x = i);\n    XorShiftRng::from_seed(seed)\n}\n\n#[test]\nfn sort() {\n    let rng = seeded_rng();\n    let mut data: Vec<u32> = rng.sample_iter(&StandardUniform).take(6 * 1024).collect();\n    let mut sorted_data = data.clone();\n    sorted_data.sort();\n    quick_sort(&mut data);\n    assert_eq!(data, sorted_data);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn sort_in_pool() {\n    let rng = seeded_rng();\n    let mut data: Vec<u32> = rng.sample_iter(&StandardUniform).take(12 * 1024).collect();\n\n    let pool = ThreadPoolBuilder::new().build().unwrap();\n    let mut sorted_data = data.clone();\n    sorted_data.sort();\n    pool.install(|| quick_sort(&mut data));\n    assert_eq!(data, sorted_data);\n}\n\n#[test]\n#[should_panic(expected = \"Hello, world!\")]\nfn panic_propagate_a() {\n    join(|| panic!(\"Hello, world!\"), || ());\n}\n\n#[test]\n#[should_panic(expected = \"Hello, world!\")]\nfn panic_propagate_b() {\n    join(|| (), || panic!(\"Hello, world!\"));\n}\n\n#[test]\n#[should_panic(expected = \"Hello, world!\")]\nfn panic_propagate_both() {\n    join(|| panic!(\"Hello, world!\"), || panic!(\"Goodbye, world!\"));\n}\n\n#[test]\n#[cfg_attr(not(panic = \"unwind\"), ignore)]\nfn panic_b_still_executes() {\n    let mut x = false;\n    match unwind::halt_unwinding(|| join(|| panic!(\"Hello, world!\"), || x = true)) {\n        Ok(_) => panic!(\"failed to propagate panic from closure A,\"),\n        Err(_) => assert!(x, \"closure b failed to execute\"),\n    }\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn join_context_both() {\n    // If we're not in a pool, both should be marked stolen as they're injected.\n    let (a_migrated, b_migrated) = join_context(|a| a.migrated(), |b| b.migrated());\n    assert!(a_migrated);\n    assert!(b_migrated);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn join_context_neither() {\n    // If we're already in a 1-thread pool, neither job should be stolen.\n    let pool = ThreadPoolBuilder::new().num_threads(1).build().unwrap();\n    let (a_migrated, b_migrated) =\n        pool.install(|| join_context(|a| a.migrated(), |b| b.migrated()));\n    assert!(!a_migrated);\n    assert!(!b_migrated);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn join_context_second() {\n    use std::sync::Barrier;\n\n    // If we're already in a 2-thread pool, the second job should be stolen.\n    let barrier = Barrier::new(2);\n    let pool = ThreadPoolBuilder::new().num_threads(2).build().unwrap();\n    let (a_migrated, b_migrated) = pool.install(|| {\n        join_context(\n            |a| {\n                barrier.wait();\n                a.migrated()\n            },\n            |b| {\n                barrier.wait();\n                b.migrated()\n            },\n        )\n    });\n    assert!(!a_migrated);\n    assert!(b_migrated);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn join_counter_overflow() {\n    const MAX: u32 = 500_000;\n\n    let mut i = 0;\n    let mut j = 0;\n    let pool = ThreadPoolBuilder::new().num_threads(2).build().unwrap();\n\n    // Hammer on join a bunch of times -- used to hit overflow debug-assertions\n    // in JEC on 32-bit targets: https://github.com/rayon-rs/rayon/issues/797\n    for _ in 0..MAX {\n        pool.join(|| i += 1, || j += 1);\n    }\n\n    assert_eq!(i, MAX);\n    assert_eq!(j, MAX);\n}\n"
  },
  {
    "path": "rayon-core/src/latch.rs",
    "content": "use std::marker::PhantomData;\nuse std::ops::Deref;\nuse std::sync::atomic::{AtomicUsize, Ordering};\nuse std::sync::Arc;\n\nuse crate::registry::{Registry, WorkerThread};\nuse crate::sync::{Condvar, Mutex};\n\n/// We define various kinds of latches, which are all a primitive signaling\n/// mechanism. A latch starts as false. Eventually someone calls `set()` and\n/// it becomes true. You can test if it has been set by calling `probe()`.\n///\n/// Some kinds of latches, but not all, support a `wait()` operation\n/// that will wait until the latch is set, blocking efficiently. That\n/// is not part of the trait since it is not possibly to do with all\n/// latches.\n///\n/// The intention is that `set()` is called once, but `probe()` may be\n/// called any number of times. Once `probe()` returns true, the memory\n/// effects that occurred before `set()` become visible.\n///\n/// It'd probably be better to refactor the API into two paired types,\n/// but that's a bit of work, and this is not a public API.\n///\n/// ## Memory ordering\n///\n/// Latches need to guarantee two things:\n///\n/// - Once `probe()` returns true, all memory effects from the `set()`\n///   are visible (in other words, the set should synchronize-with\n///   the probe).\n/// - Once `set()` occurs, the next `probe()` *will* observe it.  This\n///   typically requires a seq-cst ordering. See [the \"tickle-then-get-sleepy\" scenario in the sleep\n///   README](/src/sleep/README.md#tickle-then-get-sleepy) for details.\npub(super) trait Latch {\n    /// Set the latch, signalling others.\n    ///\n    /// # WARNING\n    ///\n    /// Setting a latch triggers other threads to wake up and (in some\n    /// cases) complete. This may, in turn, cause memory to be\n    /// deallocated and so forth. One must be very careful about this,\n    /// and it's typically better to read all the fields you will need\n    /// to access *before* a latch is set!\n    ///\n    /// This function operates on `*const Self` instead of `&self` to allow it\n    /// to become dangling during this call. The caller must ensure that the\n    /// pointer is valid upon entry, and not invalidated during the call by any\n    /// actions other than `set` itself.\n    unsafe fn set(this: *const Self);\n}\n\npub(super) trait AsCoreLatch {\n    fn as_core_latch(&self) -> &CoreLatch;\n}\n\n/// Latch is not set, owning thread is awake\nconst UNSET: usize = 0;\n\n/// Latch is not set, owning thread is going to sleep on this latch\n/// (but has not yet fallen asleep).\nconst SLEEPY: usize = 1;\n\n/// Latch is not set, owning thread is asleep on this latch and\n/// must be awoken.\nconst SLEEPING: usize = 2;\n\n/// Latch is set.\nconst SET: usize = 3;\n\n/// Spin latches are the simplest, most efficient kind, but they do\n/// not support a `wait()` operation. They just have a boolean flag\n/// that becomes true when `set()` is called.\n#[derive(Debug)]\npub(super) struct CoreLatch {\n    state: AtomicUsize,\n}\n\nimpl CoreLatch {\n    #[inline]\n    fn new() -> Self {\n        Self {\n            state: AtomicUsize::new(0),\n        }\n    }\n\n    /// Invoked by owning thread as it prepares to sleep. Returns true\n    /// if the owning thread may proceed to fall asleep, false if the\n    /// latch was set in the meantime.\n    #[inline]\n    pub(super) fn get_sleepy(&self) -> bool {\n        self.state\n            .compare_exchange(UNSET, SLEEPY, Ordering::SeqCst, Ordering::Relaxed)\n            .is_ok()\n    }\n\n    /// Invoked by owning thread as it falls asleep sleep. Returns\n    /// true if the owning thread should block, or false if the latch\n    /// was set in the meantime.\n    #[inline]\n    pub(super) fn fall_asleep(&self) -> bool {\n        self.state\n            .compare_exchange(SLEEPY, SLEEPING, Ordering::SeqCst, Ordering::Relaxed)\n            .is_ok()\n    }\n\n    /// Invoked by owning thread as it falls asleep sleep. Returns\n    /// true if the owning thread should block, or false if the latch\n    /// was set in the meantime.\n    #[inline]\n    pub(super) fn wake_up(&self) {\n        if !self.probe() {\n            let _ =\n                self.state\n                    .compare_exchange(SLEEPING, UNSET, Ordering::SeqCst, Ordering::Relaxed);\n        }\n    }\n\n    /// Set the latch. If this returns true, the owning thread was sleeping\n    /// and must be awoken.\n    ///\n    /// This is private because, typically, setting a latch involves\n    /// doing some wakeups; those are encapsulated in the surrounding\n    /// latch code.\n    #[inline]\n    unsafe fn set(this: *const Self) -> bool {\n        let old_state = (*this).state.swap(SET, Ordering::AcqRel);\n        old_state == SLEEPING\n    }\n\n    /// Test if this latch has been set.\n    #[inline]\n    pub(super) fn probe(&self) -> bool {\n        self.state.load(Ordering::Acquire) == SET\n    }\n}\n\nimpl AsCoreLatch for CoreLatch {\n    #[inline]\n    fn as_core_latch(&self) -> &CoreLatch {\n        self\n    }\n}\n\n/// Spin latches are the simplest, most efficient kind, but they do\n/// not support a `wait()` operation. They just have a boolean flag\n/// that becomes true when `set()` is called.\npub(super) struct SpinLatch<'r> {\n    core_latch: CoreLatch,\n    registry: &'r Arc<Registry>,\n    target_worker_index: usize,\n    cross: bool,\n}\n\nimpl<'r> SpinLatch<'r> {\n    /// Creates a new spin latch that is owned by `thread`. This means\n    /// that `thread` is the only thread that should be blocking on\n    /// this latch -- it also means that when the latch is set, we\n    /// will wake `thread` if it is sleeping.\n    #[inline]\n    pub(super) fn new(thread: &'r WorkerThread) -> SpinLatch<'r> {\n        SpinLatch {\n            core_latch: CoreLatch::new(),\n            registry: thread.registry(),\n            target_worker_index: thread.index(),\n            cross: false,\n        }\n    }\n\n    /// Creates a new spin latch for cross-thread-pool blocking.  Notably, we\n    /// need to make sure the registry is kept alive after setting, so we can\n    /// safely call the notification.\n    #[inline]\n    pub(super) fn cross(thread: &'r WorkerThread) -> SpinLatch<'r> {\n        SpinLatch {\n            cross: true,\n            ..SpinLatch::new(thread)\n        }\n    }\n\n    #[inline]\n    pub(super) fn probe(&self) -> bool {\n        self.core_latch.probe()\n    }\n}\n\nimpl AsCoreLatch for SpinLatch<'_> {\n    #[inline]\n    fn as_core_latch(&self) -> &CoreLatch {\n        &self.core_latch\n    }\n}\n\nimpl Latch for SpinLatch<'_> {\n    #[inline]\n    unsafe fn set(this: *const Self) {\n        let registry: &Registry = if (*this).cross {\n            // Ensure the registry stays alive while we notify it.\n            // Otherwise, it would be possible that we set the spin\n            // latch and the other thread sees it and exits, causing\n            // the registry to be deallocated, all before we get a\n            // chance to invoke `registry.notify_worker_latch_is_set`.\n            &Arc::clone((*this).registry)\n        } else {\n            // If this is not a \"cross-registry\" spin-latch, then the\n            // thread which is performing `set` is itself ensuring\n            // that the registry stays alive. However, that doesn't\n            // include this *particular* `Arc` handle if the waiting\n            // thread then exits, so we must completely dereference it.\n            (*this).registry\n        };\n        let target_worker_index = (*this).target_worker_index;\n\n        // NOTE: Once we `set`, the target may proceed and invalidate `this`!\n        if CoreLatch::set(&(*this).core_latch) {\n            // Subtle: at this point, we can no longer read from\n            // `self`, because the thread owning this spin latch may\n            // have awoken and deallocated the latch. Therefore, we\n            // only use fields whose values we already read.\n            registry.notify_worker_latch_is_set(target_worker_index);\n        }\n    }\n}\n\n/// A Latch starts as false and eventually becomes true. You can block\n/// until it becomes true.\n#[derive(Debug)]\npub(super) struct LockLatch {\n    m: Mutex<bool>,\n    v: Condvar,\n}\n\nimpl LockLatch {\n    #[inline]\n    pub(super) const fn new() -> LockLatch {\n        LockLatch {\n            m: Mutex::new(false),\n            v: Condvar::new(),\n        }\n    }\n\n    /// Block until latch is set, then resets this lock latch so it can be reused again.\n    pub(super) fn wait_and_reset(&self) {\n        let mut guard = self.m.lock().unwrap();\n        while !*guard {\n            guard = self.v.wait(guard).unwrap();\n        }\n        *guard = false;\n    }\n\n    /// Block until latch is set.\n    pub(super) fn wait(&self) {\n        let mut guard = self.m.lock().unwrap();\n        while !*guard {\n            guard = self.v.wait(guard).unwrap();\n        }\n    }\n}\n\nimpl Latch for LockLatch {\n    #[inline]\n    unsafe fn set(this: *const Self) {\n        let mut guard = (*this).m.lock().unwrap();\n        *guard = true;\n        (*this).v.notify_all();\n    }\n}\n\n/// Once latches are used to implement one-time blocking, primarily\n/// for the termination flag of the threads in the pool.\n///\n/// Note: like a `SpinLatch`, once-latches are always associated with\n/// some registry that is probing them, which must be tickled when\n/// they are set. *Unlike* a `SpinLatch`, they don't themselves hold a\n/// reference to that registry. This is because in some cases the\n/// registry owns the once-latch, and that would create a cycle. So a\n/// `OnceLatch` must be given a reference to its owning registry when\n/// it is set. For this reason, it does not implement the `Latch`\n/// trait (but it doesn't have to, as it is not used in those generic\n/// contexts).\n#[derive(Debug)]\npub(super) struct OnceLatch {\n    core_latch: CoreLatch,\n}\n\nimpl OnceLatch {\n    #[inline]\n    pub(super) fn new() -> OnceLatch {\n        Self {\n            core_latch: CoreLatch::new(),\n        }\n    }\n\n    /// Set the latch, then tickle the specific worker thread,\n    /// which should be the one that owns this latch.\n    #[inline]\n    pub(super) unsafe fn set_and_tickle_one(\n        this: *const Self,\n        registry: &Registry,\n        target_worker_index: usize,\n    ) {\n        if CoreLatch::set(&(*this).core_latch) {\n            registry.notify_worker_latch_is_set(target_worker_index);\n        }\n    }\n}\n\nimpl AsCoreLatch for OnceLatch {\n    #[inline]\n    fn as_core_latch(&self) -> &CoreLatch {\n        &self.core_latch\n    }\n}\n\n/// Counting latches are used to implement scopes. They track a\n/// counter. Unlike other latches, calling `set()` does not\n/// necessarily make the latch be considered `set()`; instead, it just\n/// decrements the counter. The latch is only \"set\" (in the sense that\n/// `probe()` returns true) once the counter reaches zero.\n#[derive(Debug)]\npub(super) struct CountLatch {\n    counter: AtomicUsize,\n    kind: CountLatchKind,\n}\n\nenum CountLatchKind {\n    /// A latch for scopes created on a rayon thread which will participate in work\n    /// stealing while it waits for completion. This thread is not necessarily part\n    /// of the same registry as the scope itself!\n    Stealing {\n        latch: CoreLatch,\n        /// If a worker thread in registry A calls `in_place_scope` on a ThreadPool\n        /// with registry B, when a job completes in a thread of registry B, we may\n        /// need to call `notify_worker_latch_is_set()` to wake the thread in registry A.\n        /// That means we need a reference to registry A (since at that point we will\n        /// only have a reference to registry B), so we stash it here.\n        registry: Arc<Registry>,\n        /// The index of the worker to wake in `registry`\n        worker_index: usize,\n    },\n\n    /// A latch for scopes created on a non-rayon thread which will block to wait.\n    Blocking { latch: LockLatch },\n}\n\nimpl std::fmt::Debug for CountLatchKind {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        match self {\n            CountLatchKind::Stealing { latch, .. } => {\n                f.debug_tuple(\"Stealing\").field(latch).finish()\n            }\n            CountLatchKind::Blocking { latch, .. } => {\n                f.debug_tuple(\"Blocking\").field(latch).finish()\n            }\n        }\n    }\n}\n\nimpl CountLatch {\n    pub(super) fn new(owner: Option<&WorkerThread>) -> Self {\n        Self::with_count(1, owner)\n    }\n\n    pub(super) fn with_count(count: usize, owner: Option<&WorkerThread>) -> Self {\n        Self {\n            counter: AtomicUsize::new(count),\n            kind: match owner {\n                Some(owner) => CountLatchKind::Stealing {\n                    latch: CoreLatch::new(),\n                    registry: Arc::clone(owner.registry()),\n                    worker_index: owner.index(),\n                },\n                None => CountLatchKind::Blocking {\n                    latch: LockLatch::new(),\n                },\n            },\n        }\n    }\n\n    #[inline]\n    pub(super) fn increment(&self) {\n        let old_counter = self.counter.fetch_add(1, Ordering::Relaxed);\n        debug_assert!(old_counter != 0);\n    }\n\n    pub(super) fn wait(&self, owner: Option<&WorkerThread>) {\n        match &self.kind {\n            CountLatchKind::Stealing {\n                latch,\n                registry,\n                worker_index,\n            } => unsafe {\n                let owner = owner.expect(\"owner thread\");\n                debug_assert_eq!(registry.id(), owner.registry().id());\n                debug_assert_eq!(*worker_index, owner.index());\n                owner.wait_until(latch);\n            },\n            CountLatchKind::Blocking { latch } => latch.wait(),\n        }\n    }\n}\n\nimpl Latch for CountLatch {\n    #[inline]\n    unsafe fn set(this: *const Self) {\n        if (*this).counter.fetch_sub(1, Ordering::SeqCst) == 1 {\n            // NOTE: Once we call `set` on the internal `latch`,\n            // the target may proceed and invalidate `this`!\n            match (*this).kind {\n                CountLatchKind::Stealing {\n                    ref latch,\n                    ref registry,\n                    worker_index,\n                } => {\n                    let registry = Arc::clone(registry);\n                    if CoreLatch::set(latch) {\n                        registry.notify_worker_latch_is_set(worker_index);\n                    }\n                }\n                CountLatchKind::Blocking { ref latch } => LockLatch::set(latch),\n            }\n        }\n    }\n}\n\n/// `&L` without any implication of `dereferenceable` for `Latch::set`\npub(super) struct LatchRef<'a, L> {\n    inner: *const L,\n    marker: PhantomData<&'a L>,\n}\n\nimpl<L> LatchRef<'_, L> {\n    pub(super) fn new(inner: &L) -> LatchRef<'_, L> {\n        LatchRef {\n            inner,\n            marker: PhantomData,\n        }\n    }\n}\n\nunsafe impl<L: Sync> Sync for LatchRef<'_, L> {}\n\nimpl<L> Deref for LatchRef<'_, L> {\n    type Target = L;\n\n    fn deref(&self) -> &L {\n        // SAFETY: if we have &self, the inner latch is still alive\n        unsafe { &*self.inner }\n    }\n}\n\nimpl<L: Latch> Latch for LatchRef<'_, L> {\n    #[inline]\n    unsafe fn set(this: *const Self) {\n        L::set((*this).inner);\n    }\n}\n"
  },
  {
    "path": "rayon-core/src/lib.rs",
    "content": "//! Rayon-core houses the core stable APIs of Rayon.\n//!\n//! These APIs have been mirrored in the Rayon crate and it is recommended to use these from there.\n//!\n//! [`join()`] is used to take two closures and potentially run them in parallel.\n//!   - It will run in parallel if task B gets stolen before task A can finish.\n//!   - It will run sequentially if task A finishes before task B is stolen and can continue on task B.\n//!\n//! [`scope()`] creates a scope in which you can run any number of parallel tasks.\n//! These tasks can spawn nested tasks and scopes, but given the nature of work stealing, the order of execution can not be guaranteed.\n//! The scope will exist until all tasks spawned within the scope have been completed.\n//!\n//! [`spawn()`] add a task into the 'static' or 'global' scope, or a local scope created by the [`scope()`] function.\n//!\n//! [`ThreadPool`] can be used to create your own thread pools (using [`ThreadPoolBuilder`]) or to customize the global one.\n//! Tasks spawned within the pool (using [`install()`][tpinstall], [`join()`][tpjoin], etc.) will be added to a deque,\n//! where it becomes available for work stealing from other threads in the local thread pool.\n//!\n//! [tpinstall]: ThreadPool::install()\n//! [tpjoin]: ThreadPool::join()\n//!\n//! # Global fallback when threading is unsupported\n//!\n//! Rayon uses `std` APIs for threading, but some targets have incomplete implementations that\n//! always return `Unsupported` errors. The WebAssembly `wasm32-unknown-unknown` and `wasm32-wasi`\n//! targets are notable examples of this. Rather than panicking on the unsupported error when\n//! creating the implicit global thread pool, Rayon configures a fallback mode instead.\n//!\n//! This fallback mode mostly functions as if it were using a single-threaded \"pool\", like setting\n//! `RAYON_NUM_THREADS=1`. For example, `join` will execute its two closures sequentially, since\n//! there is no other thread to share the work. However, since the pool is not running independent\n//! of the main thread, non-blocking calls like `spawn` may not execute at all, unless a lower-\n//! priority call like `broadcast` gives them an opening. The fallback mode does not try to emulate\n//! anything like thread preemption or `async` task switching, but `yield_now` or `yield_local`\n//! can also volunteer execution time.\n//!\n//! Explicit `ThreadPoolBuilder` methods always report their error without any fallback.\n//!\n//! # Restricting multiple versions\n//!\n//! In order to ensure proper coordination between thread pools, and especially\n//! to make sure there's only one global thread pool, `rayon-core` is actively\n//! restricted from building multiple versions of itself into a single target.\n//! You may see a build error like this in violation:\n//!\n//! ```text\n//! error: native library `rayon-core` is being linked to by more\n//! than one package, and can only be linked to by one package\n//! ```\n//!\n//! While we strive to keep `rayon-core` semver-compatible, it's still\n//! possible to arrive at this situation if different crates have overly\n//! restrictive tilde or inequality requirements for `rayon-core`.  The\n//! conflicting requirements will need to be resolved before the build will\n//! succeed.\n\n#![deny(missing_debug_implementations)]\n#![deny(missing_docs)]\n#![deny(unreachable_pub)]\n#![warn(rust_2018_idioms)]\n\nuse std::any::Any;\nuse std::env;\nuse std::error::Error;\nuse std::fmt;\nuse std::io;\nuse std::marker::PhantomData;\nuse std::str::FromStr;\nuse std::thread;\n\n#[macro_use]\nmod private;\n\nmod broadcast;\nmod job;\nmod join;\nmod latch;\nmod registry;\nmod scope;\nmod sleep;\nmod spawn;\nmod thread_pool;\nmod unwind;\n\nmod compile_fail;\nmod test;\n\npub use self::broadcast::{broadcast, spawn_broadcast, BroadcastContext};\npub use self::join::{join, join_context};\npub use self::registry::ThreadBuilder;\npub use self::scope::{in_place_scope, scope, Scope};\npub use self::scope::{in_place_scope_fifo, scope_fifo, ScopeFifo};\npub use self::spawn::{spawn, spawn_fifo};\npub use self::thread_pool::current_thread_has_pending_tasks;\npub use self::thread_pool::current_thread_index;\npub use self::thread_pool::ThreadPool;\npub use self::thread_pool::{yield_local, yield_now, Yield};\n\n#[cfg(not(feature = \"web_spin_lock\"))]\nuse std::sync;\n\n#[cfg(feature = \"web_spin_lock\")]\nuse wasm_sync as sync;\n\nuse self::registry::{CustomSpawn, DefaultSpawn, ThreadSpawn};\n\n/// Returns the maximum number of threads that Rayon supports in a single thread pool.\n///\n/// If a higher thread count is requested by calling `ThreadPoolBuilder::num_threads` or by setting\n/// the `RAYON_NUM_THREADS` environment variable, then it will be reduced to this maximum.\n///\n/// The value may vary between different targets, and is subject to change in new Rayon versions.\npub fn max_num_threads() -> usize {\n    // We are limited by the bits available in the sleep counter's `AtomicUsize`.\n    crate::sleep::THREADS_MAX\n}\n\n/// Returns the number of threads in the current registry. If this\n/// code is executing within a Rayon thread pool, then this will be\n/// the number of threads for the thread pool of the current\n/// thread. Otherwise, it will be the number of threads for the global\n/// thread pool.\n///\n/// This can be useful when trying to judge how many times to split\n/// parallel work (the parallel iterator traits use this value\n/// internally for this purpose).\n///\n/// # Future compatibility note\n///\n/// Note that unless this thread pool was created with a\n/// builder that specifies the number of threads, then this\n/// number may vary over time in future versions (see [the\n/// `num_threads()` method for details][snt]).\n///\n/// [snt]: ThreadPoolBuilder::num_threads\npub fn current_num_threads() -> usize {\n    crate::registry::Registry::current_num_threads()\n}\n\n/// Error when initializing a thread pool.\n#[derive(Debug)]\npub struct ThreadPoolBuildError {\n    kind: ErrorKind,\n}\n\n#[derive(Debug)]\nenum ErrorKind {\n    GlobalPoolAlreadyInitialized,\n    CurrentThreadAlreadyInPool,\n    IOError(io::Error),\n}\n\n/// Used to create a new [`ThreadPool`] or to configure the global rayon thread pool.\n/// ## Creating a ThreadPool\n/// The following creates a thread pool with 22 threads.\n///\n/// ```ignore-wasm\n/// # use rayon_core as rayon;\n/// let pool = rayon::ThreadPoolBuilder::new().num_threads(22).build().unwrap();\n/// ```\n///\n/// To instead configure the global thread pool, use [`build_global()`]:\n///\n/// ```ignore-wasm\n/// # use rayon_core as rayon;\n/// rayon::ThreadPoolBuilder::new().num_threads(22).build_global().unwrap();\n/// ```\n///\n/// [`build_global()`]: Self::build_global()\npub struct ThreadPoolBuilder<S = DefaultSpawn> {\n    /// The number of threads in the rayon thread pool.\n    /// If zero will use the RAYON_NUM_THREADS environment variable.\n    /// If RAYON_NUM_THREADS is invalid or zero will use the default.\n    num_threads: usize,\n\n    /// The thread we're building *from* will also be part of the pool.\n    use_current_thread: bool,\n\n    /// Custom closure, if any, to handle a panic that we cannot propagate\n    /// anywhere else.\n    panic_handler: Option<Box<PanicHandler>>,\n\n    /// Closure to compute the name of a thread.\n    get_thread_name: Option<Box<dyn FnMut(usize) -> String>>,\n\n    /// The stack size for the created worker threads\n    stack_size: Option<usize>,\n\n    /// Closure invoked on worker-thread start.\n    start_handler: Option<Box<StartHandler>>,\n\n    /// Closure invoked on worker-thread exit.\n    exit_handler: Option<Box<ExitHandler>>,\n\n    /// Closure invoked to spawn threads.\n    spawn_handler: S,\n\n    /// If false, worker threads will execute spawned jobs in a\n    /// \"depth-first\" fashion. If true, they will do a \"breadth-first\"\n    /// fashion. Depth-first is the default.\n    breadth_first: bool,\n}\n\n/// Contains the rayon thread pool configuration. Use [`ThreadPoolBuilder`] instead.\n#[deprecated(note = \"Use `ThreadPoolBuilder`\")]\n#[derive(Default)]\npub struct Configuration {\n    builder: ThreadPoolBuilder,\n}\n\n/// The type for a panic-handling closure. Note that this same closure\n/// may be invoked multiple times in parallel.\ntype PanicHandler = dyn Fn(Box<dyn Any + Send>) + Send + Sync;\n\n/// The type for a closure that gets invoked when a thread starts. The\n/// closure is passed the index of the thread on which it is invoked.\n/// Note that this same closure may be invoked multiple times in parallel.\ntype StartHandler = dyn Fn(usize) + Send + Sync;\n\n/// The type for a closure that gets invoked when a thread exits. The\n/// closure is passed the index of the thread on which it is invoked.\n/// Note that this same closure may be invoked multiple times in parallel.\ntype ExitHandler = dyn Fn(usize) + Send + Sync;\n\n// NB: We can't `#[derive(Default)]` because `S` is left ambiguous.\nimpl Default for ThreadPoolBuilder {\n    fn default() -> Self {\n        ThreadPoolBuilder {\n            num_threads: 0,\n            use_current_thread: false,\n            panic_handler: None,\n            get_thread_name: None,\n            stack_size: None,\n            start_handler: None,\n            exit_handler: None,\n            spawn_handler: DefaultSpawn,\n            breadth_first: false,\n        }\n    }\n}\n\nimpl ThreadPoolBuilder {\n    /// Creates and returns a valid rayon thread pool builder, but does not initialize it.\n    pub fn new() -> Self {\n        Self::default()\n    }\n}\n\n/// Note: the `S: ThreadSpawn` constraint is an internal implementation detail for the\n/// default spawn and those set by [`spawn_handler`](#method.spawn_handler).\nimpl<S> ThreadPoolBuilder<S>\nwhere\n    S: ThreadSpawn,\n{\n    /// Creates a new `ThreadPool` initialized using this configuration.\n    pub fn build(self) -> Result<ThreadPool, ThreadPoolBuildError> {\n        ThreadPool::build(self)\n    }\n\n    /// Initializes the global thread pool. This initialization is\n    /// **optional**.  If you do not call this function, the thread pool\n    /// will be automatically initialized with the default\n    /// configuration. Calling `build_global` is not recommended, except\n    /// in two scenarios:\n    ///\n    /// - You wish to change the default configuration.\n    /// - You are running a benchmark, in which case initializing may\n    ///   yield slightly more consistent results, since the worker threads\n    ///   will already be ready to go even in the first iteration.  But\n    ///   this cost is minimal.\n    ///\n    /// Initialization of the global thread pool happens exactly\n    /// once. Once started, the configuration cannot be\n    /// changed. Therefore, if you call `build_global` a second time, it\n    /// will return an error. An `Ok` result indicates that this\n    /// is the first initialization of the thread pool.\n    pub fn build_global(self) -> Result<(), ThreadPoolBuildError> {\n        let registry = registry::init_global_registry(self)?;\n        registry.wait_until_primed();\n        Ok(())\n    }\n}\n\nimpl ThreadPoolBuilder {\n    /// Creates a scoped `ThreadPool` initialized using this configuration.\n    ///\n    /// This is a convenience function for building a pool using [`std::thread::scope`]\n    /// to spawn threads in a [`spawn_handler`].\n    /// The threads in this pool will start by calling `wrapper`, which should\n    /// do initialization and continue by calling `ThreadBuilder::run()`.\n    ///\n    /// [`spawn_handler`]: Self::spawn_handler()\n    ///\n    /// # Examples\n    ///\n    /// A scoped pool may be useful in combination with scoped thread-local variables.\n    ///\n    /// ```ignore-wasm\n    /// # use rayon_core as rayon;\n    ///\n    /// scoped_tls::scoped_thread_local!(static POOL_DATA: Vec<i32>);\n    ///\n    /// fn main() -> Result<(), rayon::ThreadPoolBuildError> {\n    ///     let pool_data = vec![1, 2, 3];\n    ///\n    ///     // We haven't assigned any TLS data yet.\n    ///     assert!(!POOL_DATA.is_set());\n    ///\n    ///     rayon::ThreadPoolBuilder::new()\n    ///         .build_scoped(\n    ///             // Borrow `pool_data` in TLS for each thread.\n    ///             |thread| POOL_DATA.set(&pool_data, || thread.run()),\n    ///             // Do some work that needs the TLS data.\n    ///             |pool| pool.install(|| assert!(POOL_DATA.is_set())),\n    ///         )?;\n    ///\n    ///     // Once we've returned, `pool_data` is no longer borrowed.\n    ///     drop(pool_data);\n    ///     Ok(())\n    /// }\n    /// ```\n    pub fn build_scoped<W, F, R>(self, wrapper: W, with_pool: F) -> Result<R, ThreadPoolBuildError>\n    where\n        W: Fn(ThreadBuilder) + Sync, // expected to call `run()`\n        F: FnOnce(&ThreadPool) -> R,\n    {\n        std::thread::scope(|scope| {\n            let pool = self\n                .spawn_handler(|thread| {\n                    let mut builder = std::thread::Builder::new();\n                    if let Some(name) = thread.name() {\n                        builder = builder.name(name.to_string());\n                    }\n                    if let Some(size) = thread.stack_size() {\n                        builder = builder.stack_size(size);\n                    }\n                    builder.spawn_scoped(scope, || wrapper(thread))?;\n                    Ok(())\n                })\n                .build()?;\n            Ok(with_pool(&pool))\n        })\n    }\n}\n\nimpl<S> ThreadPoolBuilder<S> {\n    /// Sets a custom function for spawning threads.\n    ///\n    /// Note that the threads will not exit until after the pool is dropped. It\n    /// is up to the caller to wait for thread termination if that is important\n    /// for any invariants. For instance, threads created in [`std::thread::scope`]\n    /// will be joined before that scope returns, and this will block indefinitely\n    /// if the pool is leaked. Furthermore, the global thread pool doesn't terminate\n    /// until the entire process exits!\n    ///\n    /// # Examples\n    ///\n    /// A minimal spawn handler just needs to call `run()` from an independent thread.\n    ///\n    /// ```ignore-wasm\n    /// # use rayon_core as rayon;\n    /// fn main() -> Result<(), rayon::ThreadPoolBuildError> {\n    ///     let pool = rayon::ThreadPoolBuilder::new()\n    ///         .spawn_handler(|thread| {\n    ///             std::thread::spawn(|| thread.run());\n    ///             Ok(())\n    ///         })\n    ///         .build()?;\n    ///\n    ///     pool.install(|| println!(\"Hello from my custom thread!\"));\n    ///     Ok(())\n    /// }\n    /// ```\n    ///\n    /// The default spawn handler sets the name and stack size if given, and propagates\n    /// any errors from the thread builder.\n    ///\n    /// ```ignore-wasm\n    /// # use rayon_core as rayon;\n    /// fn main() -> Result<(), rayon::ThreadPoolBuildError> {\n    ///     let pool = rayon::ThreadPoolBuilder::new()\n    ///         .spawn_handler(|thread| {\n    ///             let mut b = std::thread::Builder::new();\n    ///             if let Some(name) = thread.name() {\n    ///                 b = b.name(name.to_owned());\n    ///             }\n    ///             if let Some(stack_size) = thread.stack_size() {\n    ///                 b = b.stack_size(stack_size);\n    ///             }\n    ///             b.spawn(|| thread.run())?;\n    ///             Ok(())\n    ///         })\n    ///         .build()?;\n    ///\n    ///     pool.install(|| println!(\"Hello from my fully custom thread!\"));\n    ///     Ok(())\n    /// }\n    /// ```\n    ///\n    /// This can also be used for a pool of scoped threads like [`crossbeam::scope`],\n    /// or [`std::thread::scope`] introduced in Rust 1.63, which is encapsulated in\n    /// [`build_scoped`].\n    ///\n    /// [`crossbeam::scope`]: https://docs.rs/crossbeam/0.8/crossbeam/fn.scope.html\n    /// [`build_scoped`]: Self::build_scoped()\n    ///\n    /// ```ignore-wasm\n    /// # use rayon_core as rayon;\n    /// fn main() -> Result<(), rayon::ThreadPoolBuildError> {\n    ///     std::thread::scope(|scope| {\n    ///         let pool = rayon::ThreadPoolBuilder::new()\n    ///             .spawn_handler(|thread| {\n    ///                 let mut builder = std::thread::Builder::new();\n    ///                 if let Some(name) = thread.name() {\n    ///                     builder = builder.name(name.to_string());\n    ///                 }\n    ///                 if let Some(size) = thread.stack_size() {\n    ///                     builder = builder.stack_size(size);\n    ///                 }\n    ///                 builder.spawn_scoped(scope, || {\n    ///                     // Add any scoped initialization here, then run!\n    ///                     thread.run()\n    ///                 })?;\n    ///                 Ok(())\n    ///             })\n    ///             .build()?;\n    ///\n    ///         pool.install(|| println!(\"Hello from my custom scoped thread!\"));\n    ///         Ok(())\n    ///     })\n    /// }\n    /// ```\n    pub fn spawn_handler<F>(self, spawn: F) -> ThreadPoolBuilder<CustomSpawn<F>>\n    where\n        F: FnMut(ThreadBuilder) -> io::Result<()>,\n    {\n        ThreadPoolBuilder {\n            spawn_handler: CustomSpawn::new(spawn),\n            // ..self\n            num_threads: self.num_threads,\n            use_current_thread: self.use_current_thread,\n            panic_handler: self.panic_handler,\n            get_thread_name: self.get_thread_name,\n            stack_size: self.stack_size,\n            start_handler: self.start_handler,\n            exit_handler: self.exit_handler,\n            breadth_first: self.breadth_first,\n        }\n    }\n\n    /// Returns a reference to the current spawn handler.\n    fn get_spawn_handler(&mut self) -> &mut S {\n        &mut self.spawn_handler\n    }\n\n    /// Get the number of threads that will be used for the thread\n    /// pool. See `num_threads()` for more information.\n    fn get_num_threads(&self) -> usize {\n        if self.num_threads > 0 {\n            self.num_threads\n        } else {\n            let default = || {\n                thread::available_parallelism()\n                    .map(|n| n.get())\n                    .unwrap_or(1)\n            };\n\n            match env::var(\"RAYON_NUM_THREADS\")\n                .ok()\n                .and_then(|s| usize::from_str(&s).ok())\n            {\n                Some(x @ 1..) => return x,\n                Some(0) => return default(),\n                _ => {}\n            }\n\n            // Support for deprecated `RAYON_RS_NUM_CPUS`.\n            match env::var(\"RAYON_RS_NUM_CPUS\")\n                .ok()\n                .and_then(|s| usize::from_str(&s).ok())\n            {\n                Some(x @ 1..) => x,\n                _ => default(),\n            }\n        }\n    }\n\n    /// Get the thread name for the thread with the given index.\n    fn get_thread_name(&mut self, index: usize) -> Option<String> {\n        let f = self.get_thread_name.as_mut()?;\n        Some(f(index))\n    }\n\n    /// Sets a closure which takes a thread index and returns\n    /// the thread's name.\n    pub fn thread_name<F>(mut self, closure: F) -> Self\n    where\n        F: FnMut(usize) -> String + 'static,\n    {\n        self.get_thread_name = Some(Box::new(closure));\n        self\n    }\n\n    /// Sets the number of threads to be used in the rayon thread pool.\n    ///\n    /// If you specify a non-zero number of threads using this\n    /// function, then the resulting thread pools are guaranteed to\n    /// start at most this number of threads.\n    ///\n    /// If `num_threads` is 0, or you do not call this function, then\n    /// the Rayon runtime will select the number of threads\n    /// automatically. At present, this is based on the\n    /// `RAYON_NUM_THREADS` environment variable (if set),\n    /// or the number of logical CPUs (otherwise).\n    /// In the future, however, the default behavior may\n    /// change to dynamically add or remove threads as needed.\n    ///\n    /// **Future compatibility warning:** Given the default behavior\n    /// may change in the future, if you wish to rely on a fixed\n    /// number of threads, you should use this function to specify\n    /// that number. To reproduce the current default behavior, you\n    /// may wish to use [`std::thread::available_parallelism`]\n    /// to query the number of CPUs dynamically.\n    ///\n    /// **Old environment variable:** `RAYON_NUM_THREADS` is a one-to-one\n    /// replacement of the now deprecated `RAYON_RS_NUM_CPUS` environment\n    /// variable. If both variables are specified, `RAYON_NUM_THREADS` will\n    /// be preferred.\n    pub fn num_threads(mut self, num_threads: usize) -> Self {\n        self.num_threads = num_threads;\n        self\n    }\n\n    /// Use the current thread as one of the threads in the pool.\n    ///\n    /// The current thread is guaranteed to be at index 0, and since the thread is not managed by\n    /// rayon, the spawn and exit handlers do not run for that thread.\n    ///\n    /// Note that the current thread won't run the main work-stealing loop, so jobs spawned into\n    /// the thread pool will generally not be picked up automatically by this thread unless you\n    /// yield to rayon in some way, like via [`yield_now()`], [`yield_local()`], or [`scope()`].\n    ///\n    /// # Local thread pools\n    ///\n    /// Using this in a local thread pool means the registry will be leaked. In future versions\n    /// there might be a way of cleaning up the current-thread state.\n    pub fn use_current_thread(mut self) -> Self {\n        self.use_current_thread = true;\n        self\n    }\n\n    /// Returns a copy of the current panic handler.\n    fn take_panic_handler(&mut self) -> Option<Box<PanicHandler>> {\n        self.panic_handler.take()\n    }\n\n    /// Normally, whenever Rayon catches a panic, it tries to\n    /// propagate it to someplace sensible, to try and reflect the\n    /// semantics of sequential execution. But in some cases,\n    /// particularly with the `spawn()` APIs, there is no\n    /// obvious place where we should propagate the panic to.\n    /// In that case, this panic handler is invoked.\n    ///\n    /// If no panic handler is set, the default is to abort the\n    /// process, under the principle that panics should not go\n    /// unobserved.\n    ///\n    /// If the panic handler itself panics, this will abort the\n    /// process. To prevent this, wrap the body of your panic handler\n    /// in a call to `std::panic::catch_unwind()`.\n    pub fn panic_handler<H>(mut self, panic_handler: H) -> Self\n    where\n        H: Fn(Box<dyn Any + Send>) + Send + Sync + 'static,\n    {\n        self.panic_handler = Some(Box::new(panic_handler));\n        self\n    }\n\n    /// Get the stack size of the worker threads\n    fn get_stack_size(&self) -> Option<usize> {\n        self.stack_size\n    }\n\n    /// Sets the stack size of the worker threads\n    pub fn stack_size(mut self, stack_size: usize) -> Self {\n        self.stack_size = Some(stack_size);\n        self\n    }\n\n    /// **(DEPRECATED)** Suggest to worker threads that they execute\n    /// spawned jobs in a \"breadth-first\" fashion.\n    ///\n    /// Typically, when a worker thread is idle or blocked, it will\n    /// attempt to execute the job from the *top* of its local deque of\n    /// work (i.e., the job most recently spawned). If this flag is set\n    /// to true, however, workers will prefer to execute in a\n    /// *breadth-first* fashion -- that is, they will search for jobs at\n    /// the *bottom* of their local deque. (At present, workers *always*\n    /// steal from the bottom of other workers' deques, regardless of\n    /// the setting of this flag.)\n    ///\n    /// If you think of the tasks as a tree, where a parent task\n    /// spawns its children in the tree, then this flag loosely\n    /// corresponds to doing a breadth-first traversal of the tree,\n    /// whereas the default would be to do a depth-first traversal.\n    ///\n    /// **Note that this is an \"execution hint\".** Rayon's task\n    /// execution is highly dynamic and the precise order in which\n    /// independent tasks are executed is not intended to be\n    /// guaranteed.\n    ///\n    /// This `breadth_first()` method is now deprecated per [RFC #1],\n    /// and in the future its effect may be removed. Consider using\n    /// [`scope_fifo()`] for a similar effect.\n    ///\n    /// [RFC #1]: https://github.com/rayon-rs/rfcs/blob/main/accepted/rfc0001-scope-scheduling.md\n    #[deprecated(note = \"use `scope_fifo` and `spawn_fifo` for similar effect\")]\n    pub fn breadth_first(mut self) -> Self {\n        self.breadth_first = true;\n        self\n    }\n\n    fn get_breadth_first(&self) -> bool {\n        self.breadth_first\n    }\n\n    /// Takes the current thread start callback, leaving `None`.\n    fn take_start_handler(&mut self) -> Option<Box<StartHandler>> {\n        self.start_handler.take()\n    }\n\n    /// Sets a callback to be invoked on thread start.\n    ///\n    /// The closure is passed the index of the thread on which it is invoked.\n    /// Note that this same closure may be invoked multiple times in parallel.\n    /// If this closure panics, the panic will be passed to the panic handler.\n    /// If that handler returns, then startup will continue normally.\n    pub fn start_handler<H>(mut self, start_handler: H) -> Self\n    where\n        H: Fn(usize) + Send + Sync + 'static,\n    {\n        self.start_handler = Some(Box::new(start_handler));\n        self\n    }\n\n    /// Returns a current thread exit callback, leaving `None`.\n    fn take_exit_handler(&mut self) -> Option<Box<ExitHandler>> {\n        self.exit_handler.take()\n    }\n\n    /// Sets a callback to be invoked on thread exit.\n    ///\n    /// The closure is passed the index of the thread on which it is invoked.\n    /// Note that this same closure may be invoked multiple times in parallel.\n    /// If this closure panics, the panic will be passed to the panic handler.\n    /// If that handler returns, then the thread will exit normally.\n    pub fn exit_handler<H>(mut self, exit_handler: H) -> Self\n    where\n        H: Fn(usize) + Send + Sync + 'static,\n    {\n        self.exit_handler = Some(Box::new(exit_handler));\n        self\n    }\n}\n\n#[allow(deprecated)]\nimpl Configuration {\n    /// Creates and return a valid rayon thread pool configuration, but does not initialize it.\n    pub fn new() -> Configuration {\n        Configuration {\n            builder: ThreadPoolBuilder::new(),\n        }\n    }\n\n    /// Deprecated in favor of `ThreadPoolBuilder::build`.\n    pub fn build(self) -> Result<ThreadPool, Box<dyn Error + 'static>> {\n        self.builder.build().map_err(Box::from)\n    }\n\n    /// Deprecated in favor of `ThreadPoolBuilder::thread_name`.\n    pub fn thread_name<F>(mut self, closure: F) -> Self\n    where\n        F: FnMut(usize) -> String + 'static,\n    {\n        self.builder = self.builder.thread_name(closure);\n        self\n    }\n\n    /// Deprecated in favor of `ThreadPoolBuilder::num_threads`.\n    pub fn num_threads(mut self, num_threads: usize) -> Configuration {\n        self.builder = self.builder.num_threads(num_threads);\n        self\n    }\n\n    /// Deprecated in favor of `ThreadPoolBuilder::panic_handler`.\n    pub fn panic_handler<H>(mut self, panic_handler: H) -> Configuration\n    where\n        H: Fn(Box<dyn Any + Send>) + Send + Sync + 'static,\n    {\n        self.builder = self.builder.panic_handler(panic_handler);\n        self\n    }\n\n    /// Deprecated in favor of `ThreadPoolBuilder::stack_size`.\n    pub fn stack_size(mut self, stack_size: usize) -> Self {\n        self.builder = self.builder.stack_size(stack_size);\n        self\n    }\n\n    /// Deprecated in favor of `ThreadPoolBuilder::breadth_first`.\n    pub fn breadth_first(mut self) -> Self {\n        self.builder = self.builder.breadth_first();\n        self\n    }\n\n    /// Deprecated in favor of `ThreadPoolBuilder::start_handler`.\n    pub fn start_handler<H>(mut self, start_handler: H) -> Configuration\n    where\n        H: Fn(usize) + Send + Sync + 'static,\n    {\n        self.builder = self.builder.start_handler(start_handler);\n        self\n    }\n\n    /// Deprecated in favor of `ThreadPoolBuilder::exit_handler`.\n    pub fn exit_handler<H>(mut self, exit_handler: H) -> Configuration\n    where\n        H: Fn(usize) + Send + Sync + 'static,\n    {\n        self.builder = self.builder.exit_handler(exit_handler);\n        self\n    }\n\n    /// Returns a ThreadPoolBuilder with identical parameters.\n    fn into_builder(self) -> ThreadPoolBuilder {\n        self.builder\n    }\n}\n\nimpl ThreadPoolBuildError {\n    fn new(kind: ErrorKind) -> ThreadPoolBuildError {\n        ThreadPoolBuildError { kind }\n    }\n\n    fn is_unsupported(&self) -> bool {\n        matches!(&self.kind, ErrorKind::IOError(e) if e.kind() == io::ErrorKind::Unsupported)\n    }\n}\n\nconst GLOBAL_POOL_ALREADY_INITIALIZED: &str =\n    \"The global thread pool has already been initialized.\";\n\nconst CURRENT_THREAD_ALREADY_IN_POOL: &str =\n    \"The current thread is already part of another thread pool.\";\n\nimpl Error for ThreadPoolBuildError {\n    #[allow(deprecated)]\n    fn description(&self) -> &str {\n        match self.kind {\n            ErrorKind::GlobalPoolAlreadyInitialized => GLOBAL_POOL_ALREADY_INITIALIZED,\n            ErrorKind::CurrentThreadAlreadyInPool => CURRENT_THREAD_ALREADY_IN_POOL,\n            ErrorKind::IOError(ref e) => e.description(),\n        }\n    }\n\n    fn source(&self) -> Option<&(dyn Error + 'static)> {\n        match &self.kind {\n            ErrorKind::GlobalPoolAlreadyInitialized | ErrorKind::CurrentThreadAlreadyInPool => None,\n            ErrorKind::IOError(e) => Some(e),\n        }\n    }\n}\n\nimpl fmt::Display for ThreadPoolBuildError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match &self.kind {\n            ErrorKind::CurrentThreadAlreadyInPool => CURRENT_THREAD_ALREADY_IN_POOL.fmt(f),\n            ErrorKind::GlobalPoolAlreadyInitialized => GLOBAL_POOL_ALREADY_INITIALIZED.fmt(f),\n            ErrorKind::IOError(e) => e.fmt(f),\n        }\n    }\n}\n\n/// Deprecated in favor of `ThreadPoolBuilder::build_global`.\n#[deprecated(note = \"use `ThreadPoolBuilder::build_global`\")]\n#[allow(deprecated)]\npub fn initialize(config: Configuration) -> Result<(), Box<dyn Error>> {\n    config.into_builder().build_global().map_err(Box::from)\n}\n\nimpl<S> fmt::Debug for ThreadPoolBuilder<S> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        let ThreadPoolBuilder {\n            ref num_threads,\n            ref use_current_thread,\n            ref get_thread_name,\n            ref panic_handler,\n            ref stack_size,\n            ref start_handler,\n            ref exit_handler,\n            spawn_handler: _,\n            ref breadth_first,\n        } = *self;\n\n        // Just print `Some(<closure>)` or `None` to the debug\n        // output.\n        struct ClosurePlaceholder;\n        impl fmt::Debug for ClosurePlaceholder {\n            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n                f.write_str(\"<closure>\")\n            }\n        }\n        let get_thread_name = get_thread_name.as_ref().map(|_| ClosurePlaceholder);\n        let panic_handler = panic_handler.as_ref().map(|_| ClosurePlaceholder);\n        let start_handler = start_handler.as_ref().map(|_| ClosurePlaceholder);\n        let exit_handler = exit_handler.as_ref().map(|_| ClosurePlaceholder);\n\n        f.debug_struct(\"ThreadPoolBuilder\")\n            .field(\"num_threads\", num_threads)\n            .field(\"use_current_thread\", use_current_thread)\n            .field(\"get_thread_name\", &get_thread_name)\n            .field(\"panic_handler\", &panic_handler)\n            .field(\"stack_size\", &stack_size)\n            .field(\"start_handler\", &start_handler)\n            .field(\"exit_handler\", &exit_handler)\n            .field(\"breadth_first\", &breadth_first)\n            .finish()\n    }\n}\n\n#[allow(deprecated)]\nimpl fmt::Debug for Configuration {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.builder.fmt(f)\n    }\n}\n\n/// Provides the calling context to a closure called by `join_context`.\n#[derive(Debug)]\npub struct FnContext {\n    migrated: bool,\n\n    /// disable `Send` and `Sync`, just for a little future-proofing.\n    _marker: PhantomData<*mut ()>,\n}\n\nimpl FnContext {\n    #[inline]\n    fn new(migrated: bool) -> Self {\n        FnContext {\n            migrated,\n            _marker: PhantomData,\n        }\n    }\n}\n\nimpl FnContext {\n    /// Returns `true` if the closure was called from a different thread\n    /// than it was provided from.\n    #[inline]\n    pub fn migrated(&self) -> bool {\n        self.migrated\n    }\n}\n"
  },
  {
    "path": "rayon-core/src/private.rs",
    "content": "//! The public parts of this private module are used to create traits\n//! that cannot be implemented outside of our own crate.  This way we\n//! can feel free to extend those traits without worrying about it\n//! being a breaking change for other implementations.\n\n/// If this type is pub but not publicly reachable, third parties\n/// can't name it and can't implement traits using it.\n#[allow(missing_debug_implementations)]\npub struct PrivateMarker;\n\nmacro_rules! private_decl {\n    () => {\n        /// This trait is private; this method exists to make it\n        /// impossible to implement outside the crate.\n        #[doc(hidden)]\n        fn __rayon_private__(&self) -> crate::private::PrivateMarker;\n    };\n}\n\nmacro_rules! private_impl {\n    () => {\n        fn __rayon_private__(&self) -> crate::private::PrivateMarker {\n            crate::private::PrivateMarker\n        }\n    };\n}\n"
  },
  {
    "path": "rayon-core/src/registry.rs",
    "content": "use crate::job::{JobFifo, JobRef, StackJob};\nuse crate::latch::{AsCoreLatch, CoreLatch, Latch, LatchRef, LockLatch, OnceLatch, SpinLatch};\nuse crate::sleep::Sleep;\nuse crate::sync::Mutex;\nuse crate::unwind;\nuse crate::{\n    ErrorKind, ExitHandler, PanicHandler, StartHandler, ThreadPoolBuildError, ThreadPoolBuilder,\n    Yield,\n};\nuse crossbeam_deque::{Injector, Steal, Stealer, Worker};\nuse std::cell::Cell;\nuse std::fmt;\nuse std::hash::{DefaultHasher, Hasher};\nuse std::io;\nuse std::mem;\nuse std::ptr;\nuse std::sync::atomic::{AtomicUsize, Ordering};\nuse std::sync::{Arc, Once};\nuse std::thread;\n\n/// Thread builder used for customization via [`ThreadPoolBuilder::spawn_handler()`].\npub struct ThreadBuilder {\n    name: Option<String>,\n    stack_size: Option<usize>,\n    worker: Worker<JobRef>,\n    stealer: Stealer<JobRef>,\n    registry: Arc<Registry>,\n    index: usize,\n}\n\nimpl ThreadBuilder {\n    /// Gets the index of this thread in the pool, within `0..num_threads`.\n    pub fn index(&self) -> usize {\n        self.index\n    }\n\n    /// Gets the string that was specified by `ThreadPoolBuilder::name()`.\n    pub fn name(&self) -> Option<&str> {\n        self.name.as_deref()\n    }\n\n    /// Gets the value that was specified by `ThreadPoolBuilder::stack_size()`.\n    pub fn stack_size(&self) -> Option<usize> {\n        self.stack_size\n    }\n\n    /// Executes the main loop for this thread. This will not return until the\n    /// thread pool is dropped.\n    pub fn run(self) {\n        unsafe { main_loop(self) }\n    }\n}\n\nimpl fmt::Debug for ThreadBuilder {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"ThreadBuilder\")\n            .field(\"pool\", &self.registry.id())\n            .field(\"index\", &self.index)\n            .field(\"name\", &self.name)\n            .field(\"stack_size\", &self.stack_size)\n            .finish()\n    }\n}\n\n/// Generalized trait for spawning a thread in the `Registry`.\n///\n/// This trait is pub-in-private -- E0445 forces us to make it public,\n/// but we don't actually want to expose these details in the API.\npub trait ThreadSpawn {\n    private_decl! {}\n\n    /// Spawn a thread with the `ThreadBuilder` parameters, and then\n    /// call `ThreadBuilder::run()`.\n    fn spawn(&mut self, thread: ThreadBuilder) -> io::Result<()>;\n}\n\n/// Spawns a thread in the \"normal\" way with `std::thread::Builder`.\n///\n/// This type is pub-in-private -- E0445 forces us to make it public,\n/// but we don't actually want to expose these details in the API.\n#[derive(Debug, Default)]\npub struct DefaultSpawn;\n\nimpl ThreadSpawn for DefaultSpawn {\n    private_impl! {}\n\n    fn spawn(&mut self, thread: ThreadBuilder) -> io::Result<()> {\n        let mut b = thread::Builder::new();\n        if let Some(name) = thread.name() {\n            b = b.name(name.to_owned());\n        }\n        if let Some(stack_size) = thread.stack_size() {\n            b = b.stack_size(stack_size);\n        }\n        b.spawn(|| thread.run())?;\n        Ok(())\n    }\n}\n\n/// Spawns a thread with a user's custom callback.\n///\n/// This type is pub-in-private -- E0445 forces us to make it public,\n/// but we don't actually want to expose these details in the API.\n#[derive(Debug)]\npub struct CustomSpawn<F>(F);\n\nimpl<F> CustomSpawn<F>\nwhere\n    F: FnMut(ThreadBuilder) -> io::Result<()>,\n{\n    pub(super) fn new(spawn: F) -> Self {\n        CustomSpawn(spawn)\n    }\n}\n\nimpl<F> ThreadSpawn for CustomSpawn<F>\nwhere\n    F: FnMut(ThreadBuilder) -> io::Result<()>,\n{\n    private_impl! {}\n\n    #[inline]\n    fn spawn(&mut self, thread: ThreadBuilder) -> io::Result<()> {\n        (self.0)(thread)\n    }\n}\n\npub(super) struct Registry {\n    thread_infos: Vec<ThreadInfo>,\n    sleep: Sleep,\n    injected_jobs: Injector<JobRef>,\n    broadcasts: Mutex<Vec<Worker<JobRef>>>,\n    panic_handler: Option<Box<PanicHandler>>,\n    start_handler: Option<Box<StartHandler>>,\n    exit_handler: Option<Box<ExitHandler>>,\n\n    // When this latch reaches 0, it means that all work on this\n    // registry must be complete. This is ensured in the following ways:\n    //\n    // - if this is the global registry, there is a ref-count that never\n    //   gets released.\n    // - if this is a user-created thread pool, then so long as the thread pool\n    //   exists, it holds a reference.\n    // - when we inject a \"blocking job\" into the registry with `ThreadPool::install()`,\n    //   no adjustment is needed; the `ThreadPool` holds the reference, and since we won't\n    //   return until the blocking job is complete, that ref will continue to be held.\n    // - when `join()` or `scope()` is invoked, similarly, no adjustments are needed.\n    //   These are always owned by some other job (e.g., one injected by `ThreadPool::install()`)\n    //   and that job will keep the pool alive.\n    terminate_count: AtomicUsize,\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Initialization\n\nstatic mut THE_REGISTRY: Option<Arc<Registry>> = None;\nstatic THE_REGISTRY_SET: Once = Once::new();\n\n/// Starts the worker threads (if that has not already happened). If\n/// initialization has not already occurred, use the default\n/// configuration.\npub(super) fn global_registry() -> &'static Arc<Registry> {\n    set_global_registry(default_global_registry)\n        .or_else(|err| {\n            // SAFETY: we only create a shared reference to `THE_REGISTRY` after the `call_once`\n            // that initializes it, and there will be no more mutable accesses at all.\n            debug_assert!(THE_REGISTRY_SET.is_completed());\n            let the_registry = unsafe { &*ptr::addr_of!(THE_REGISTRY) };\n            the_registry.as_ref().ok_or(err)\n        })\n        .expect(\"The global thread pool has not been initialized.\")\n}\n\n/// Starts the worker threads (if that has not already happened) with\n/// the given builder.\npub(super) fn init_global_registry<S>(\n    builder: ThreadPoolBuilder<S>,\n) -> Result<&'static Arc<Registry>, ThreadPoolBuildError>\nwhere\n    S: ThreadSpawn,\n{\n    set_global_registry(|| Registry::new(builder))\n}\n\n/// Starts the worker threads (if that has not already happened)\n/// by creating a registry with the given callback.\nfn set_global_registry<F>(registry: F) -> Result<&'static Arc<Registry>, ThreadPoolBuildError>\nwhere\n    F: FnOnce() -> Result<Arc<Registry>, ThreadPoolBuildError>,\n{\n    let mut result = Err(ThreadPoolBuildError::new(\n        ErrorKind::GlobalPoolAlreadyInitialized,\n    ));\n\n    THE_REGISTRY_SET.call_once(|| {\n        result = registry().map(|registry: Arc<Registry>| {\n            // SAFETY: this is the only mutable access to `THE_REGISTRY`, thanks to `Once`, and\n            // `global_registry()` only takes a shared reference **after** this `call_once`.\n            unsafe {\n                ptr::addr_of_mut!(THE_REGISTRY).write(Some(registry));\n                (*ptr::addr_of!(THE_REGISTRY)).as_ref().unwrap_unchecked()\n            }\n        })\n    });\n\n    result\n}\n\nfn default_global_registry() -> Result<Arc<Registry>, ThreadPoolBuildError> {\n    let result = Registry::new(ThreadPoolBuilder::new());\n\n    // If we're running in an environment that doesn't support threads at all, we can fall back to\n    // using the current thread alone. This is crude, and probably won't work for non-blocking\n    // calls like `spawn` or `broadcast_spawn`, but a lot of stuff does work fine.\n    //\n    // Notably, this allows current WebAssembly targets to work even though their threading support\n    // is stubbed out, and we won't have to change anything if they do add real threading.\n    let unsupported = matches!(&result, Err(e) if e.is_unsupported());\n    if unsupported && WorkerThread::current().is_null() {\n        let builder = ThreadPoolBuilder::new().num_threads(1).use_current_thread();\n        let fallback_result = Registry::new(builder);\n        if fallback_result.is_ok() {\n            return fallback_result;\n        }\n    }\n\n    result\n}\n\nstruct Terminator<'a>(&'a Arc<Registry>);\n\nimpl<'a> Drop for Terminator<'a> {\n    fn drop(&mut self) {\n        self.0.terminate()\n    }\n}\n\nimpl Registry {\n    pub(super) fn new<S>(\n        mut builder: ThreadPoolBuilder<S>,\n    ) -> Result<Arc<Self>, ThreadPoolBuildError>\n    where\n        S: ThreadSpawn,\n    {\n        // Soft-limit the number of threads that we can actually support.\n        let n_threads = Ord::min(builder.get_num_threads(), crate::max_num_threads());\n\n        let breadth_first = builder.get_breadth_first();\n\n        let (workers, stealers): (Vec<_>, Vec<_>) = (0..n_threads)\n            .map(|_| {\n                let worker = if breadth_first {\n                    Worker::new_fifo()\n                } else {\n                    Worker::new_lifo()\n                };\n\n                let stealer = worker.stealer();\n                (worker, stealer)\n            })\n            .unzip();\n\n        let (broadcasts, broadcast_stealers): (Vec<_>, Vec<_>) = (0..n_threads)\n            .map(|_| {\n                let worker = Worker::new_fifo();\n                let stealer = worker.stealer();\n                (worker, stealer)\n            })\n            .unzip();\n\n        let registry = Arc::new(Registry {\n            thread_infos: stealers.into_iter().map(ThreadInfo::new).collect(),\n            sleep: Sleep::new(n_threads),\n            injected_jobs: Injector::new(),\n            broadcasts: Mutex::new(broadcasts),\n            terminate_count: AtomicUsize::new(1),\n            panic_handler: builder.take_panic_handler(),\n            start_handler: builder.take_start_handler(),\n            exit_handler: builder.take_exit_handler(),\n        });\n\n        // If we return early or panic, make sure to terminate existing threads.\n        let t1000 = Terminator(&registry);\n\n        for (index, (worker, stealer)) in workers.into_iter().zip(broadcast_stealers).enumerate() {\n            let thread = ThreadBuilder {\n                name: builder.get_thread_name(index),\n                stack_size: builder.get_stack_size(),\n                registry: Arc::clone(&registry),\n                worker,\n                stealer,\n                index,\n            };\n\n            if index == 0 && builder.use_current_thread {\n                if !WorkerThread::current().is_null() {\n                    return Err(ThreadPoolBuildError::new(\n                        ErrorKind::CurrentThreadAlreadyInPool,\n                    ));\n                }\n                // Rather than starting a new thread, we're just taking over the current thread\n                // *without* running the main loop, so we can still return from here.\n                // The WorkerThread is leaked, but we never shutdown the global pool anyway.\n                let worker_thread = Box::into_raw(Box::new(WorkerThread::from(thread)));\n\n                unsafe {\n                    WorkerThread::set_current(worker_thread);\n                    Latch::set(&registry.thread_infos[index].primed);\n                }\n                continue;\n            }\n\n            if let Err(e) = builder.get_spawn_handler().spawn(thread) {\n                return Err(ThreadPoolBuildError::new(ErrorKind::IOError(e)));\n            }\n        }\n\n        // Returning normally now, without termination.\n        mem::forget(t1000);\n\n        Ok(registry)\n    }\n\n    pub(super) fn current() -> Arc<Registry> {\n        unsafe {\n            let worker_thread = WorkerThread::current();\n            let registry = if worker_thread.is_null() {\n                global_registry()\n            } else {\n                &(*worker_thread).registry\n            };\n            Arc::clone(registry)\n        }\n    }\n\n    /// Returns the number of threads in the current registry.  This\n    /// is better than `Registry::current().num_threads()` because it\n    /// avoids incrementing the `Arc`.\n    pub(super) fn current_num_threads() -> usize {\n        unsafe {\n            let worker_thread = WorkerThread::current();\n            if worker_thread.is_null() {\n                global_registry().num_threads()\n            } else {\n                (*worker_thread).registry.num_threads()\n            }\n        }\n    }\n\n    /// Returns the current `WorkerThread` if it's part of this `Registry`.\n    pub(super) fn current_thread(&self) -> Option<&WorkerThread> {\n        unsafe {\n            let worker = WorkerThread::current().as_ref()?;\n            if worker.registry().id() == self.id() {\n                Some(worker)\n            } else {\n                None\n            }\n        }\n    }\n\n    /// Returns an opaque identifier for this registry.\n    pub(super) fn id(&self) -> RegistryId {\n        // We can rely on `self` not to change since we only ever create\n        // registries that are boxed up in an `Arc` (see `new()` above).\n        RegistryId {\n            addr: self as *const Self as usize,\n        }\n    }\n\n    pub(super) fn num_threads(&self) -> usize {\n        self.thread_infos.len()\n    }\n\n    pub(super) fn catch_unwind(&self, f: impl FnOnce()) {\n        if let Err(err) = unwind::halt_unwinding(f) {\n            // If there is no handler, or if that handler itself panics, then we abort.\n            let abort_guard = unwind::AbortIfPanic;\n            if let Some(ref handler) = self.panic_handler {\n                handler(err);\n                mem::forget(abort_guard);\n            }\n        }\n    }\n\n    /// Waits for the worker threads to get up and running.  This is\n    /// meant to be used for benchmarking purposes, primarily, so that\n    /// you can get more consistent numbers by having everything\n    /// \"ready to go\".\n    pub(super) fn wait_until_primed(&self) {\n        for info in &self.thread_infos {\n            info.primed.wait();\n        }\n    }\n\n    /// Waits for the worker threads to stop. This is used for testing\n    /// -- so we can check that termination actually works.\n    #[cfg(test)]\n    pub(super) fn wait_until_stopped(&self) {\n        for info in &self.thread_infos {\n            info.stopped.wait();\n        }\n    }\n\n    // ////////////////////////////////////////////////////////////////////////\n    // MAIN LOOP\n    //\n    // So long as all of the worker threads are hanging out in their\n    // top-level loop, there is no work to be done.\n\n    /// Push a job into the given `registry`. If we are running on a\n    /// worker thread for the registry, this will push onto the\n    /// deque. Else, it will inject from the outside (which is slower).\n    pub(super) fn inject_or_push(&self, job_ref: JobRef) {\n        let worker_thread = WorkerThread::current();\n        unsafe {\n            if !worker_thread.is_null() && (*worker_thread).registry().id() == self.id() {\n                (*worker_thread).push(job_ref);\n            } else {\n                self.inject(job_ref);\n            }\n        }\n    }\n\n    /// Push a job into the \"external jobs\" queue; it will be taken by\n    /// whatever worker has nothing to do. Use this if you know that\n    /// you are not on a worker of this registry.\n    pub(super) fn inject(&self, injected_job: JobRef) {\n        // It should not be possible for `state.terminate` to be true\n        // here. It is only set to true when the user creates (and\n        // drops) a `ThreadPool`; and, in that case, they cannot be\n        // calling `inject()` later, since they dropped their\n        // `ThreadPool`.\n        debug_assert_ne!(\n            self.terminate_count.load(Ordering::Acquire),\n            0,\n            \"inject() sees state.terminate as true\"\n        );\n\n        let queue_was_empty = self.injected_jobs.is_empty();\n\n        self.injected_jobs.push(injected_job);\n        self.sleep.new_injected_jobs(1, queue_was_empty);\n    }\n\n    fn has_injected_job(&self) -> bool {\n        !self.injected_jobs.is_empty()\n    }\n\n    fn pop_injected_job(&self) -> Option<JobRef> {\n        loop {\n            match self.injected_jobs.steal() {\n                Steal::Success(job) => return Some(job),\n                Steal::Empty => return None,\n                Steal::Retry => {}\n            }\n        }\n    }\n\n    /// Push a job into each thread's own \"external jobs\" queue; it will be\n    /// executed only on that thread, when it has nothing else to do locally,\n    /// before it tries to steal other work.\n    ///\n    /// **Panics** if not given exactly as many jobs as there are threads.\n    pub(super) fn inject_broadcast(&self, injected_jobs: impl ExactSizeIterator<Item = JobRef>) {\n        assert_eq!(self.num_threads(), injected_jobs.len());\n        {\n            let broadcasts = self.broadcasts.lock().unwrap();\n\n            // It should not be possible for `state.terminate` to be true\n            // here. It is only set to true when the user creates (and\n            // drops) a `ThreadPool`; and, in that case, they cannot be\n            // calling `inject_broadcast()` later, since they dropped their\n            // `ThreadPool`.\n            debug_assert_ne!(\n                self.terminate_count.load(Ordering::Acquire),\n                0,\n                \"inject_broadcast() sees state.terminate as true\"\n            );\n\n            assert_eq!(broadcasts.len(), injected_jobs.len());\n            for (worker, job_ref) in broadcasts.iter().zip(injected_jobs) {\n                worker.push(job_ref);\n            }\n        }\n        for i in 0..self.num_threads() {\n            self.sleep.notify_worker_latch_is_set(i);\n        }\n    }\n\n    /// If already in a worker-thread of this registry, just execute `op`.\n    /// Otherwise, inject `op` in this thread pool. Either way, block until `op`\n    /// completes and return its return value. If `op` panics, that panic will\n    /// be propagated as well.  The second argument indicates `true` if injection\n    /// was performed, `false` if executed directly.\n    pub(super) fn in_worker<OP, R>(&self, op: OP) -> R\n    where\n        OP: FnOnce(&WorkerThread, bool) -> R + Send,\n        R: Send,\n    {\n        unsafe {\n            let worker_thread = WorkerThread::current();\n            if worker_thread.is_null() {\n                self.in_worker_cold(op)\n            } else if (*worker_thread).registry().id() != self.id() {\n                self.in_worker_cross(&*worker_thread, op)\n            } else {\n                // Perfectly valid to give them a `&T`: this is the\n                // current thread, so we know the data structure won't be\n                // invalidated until we return.\n                op(&*worker_thread, false)\n            }\n        }\n    }\n\n    #[cold]\n    unsafe fn in_worker_cold<OP, R>(&self, op: OP) -> R\n    where\n        OP: FnOnce(&WorkerThread, bool) -> R + Send,\n        R: Send,\n    {\n        thread_local!(static LOCK_LATCH: LockLatch = const { LockLatch::new() });\n\n        LOCK_LATCH.with(|l| {\n            // This thread isn't a member of *any* thread pool, so just block.\n            debug_assert!(WorkerThread::current().is_null());\n            let job = StackJob::new(\n                |injected| {\n                    let worker_thread = WorkerThread::current();\n                    assert!(injected && !worker_thread.is_null());\n                    op(&*worker_thread, true)\n                },\n                LatchRef::new(l),\n            );\n            self.inject(job.as_job_ref());\n            job.latch.wait_and_reset(); // Make sure we can use the same latch again next time.\n\n            job.into_result()\n        })\n    }\n\n    #[cold]\n    unsafe fn in_worker_cross<OP, R>(&self, current_thread: &WorkerThread, op: OP) -> R\n    where\n        OP: FnOnce(&WorkerThread, bool) -> R + Send,\n        R: Send,\n    {\n        // This thread is a member of a different pool, so let it process\n        // other work while waiting for this `op` to complete.\n        debug_assert!(current_thread.registry().id() != self.id());\n        let latch = SpinLatch::cross(current_thread);\n        let job = StackJob::new(\n            |injected| {\n                let worker_thread = WorkerThread::current();\n                assert!(injected && !worker_thread.is_null());\n                op(&*worker_thread, true)\n            },\n            latch,\n        );\n        self.inject(job.as_job_ref());\n        current_thread.wait_until(&job.latch);\n        job.into_result()\n    }\n\n    /// Increments the terminate counter. This increment should be\n    /// balanced by a call to `terminate`, which will decrement. This\n    /// is used when spawning asynchronous work, which needs to\n    /// prevent the registry from terminating so long as it is active.\n    ///\n    /// Note that blocking functions such as `join` and `scope` do not\n    /// need to concern themselves with this fn; their context is\n    /// responsible for ensuring the current thread pool will not\n    /// terminate until they return.\n    ///\n    /// The global thread pool always has an outstanding reference\n    /// (the initial one). Custom thread pools have one outstanding\n    /// reference that is dropped when the `ThreadPool` is dropped:\n    /// since installing the thread pool blocks until any joins/scopes\n    /// complete, this ensures that joins/scopes are covered.\n    ///\n    /// The exception is `::spawn()`, which can create a job outside\n    /// of any blocking scope. In that case, the job itself holds a\n    /// terminate count and is responsible for invoking `terminate()`\n    /// when finished.\n    pub(super) fn increment_terminate_count(&self) {\n        let previous = self.terminate_count.fetch_add(1, Ordering::AcqRel);\n        debug_assert!(previous != 0, \"registry ref count incremented from zero\");\n        assert!(previous != usize::MAX, \"overflow in registry ref count\");\n    }\n\n    /// Signals that the thread pool which owns this registry has been\n    /// dropped. The worker threads will gradually terminate, once any\n    /// extant work is completed.\n    pub(super) fn terminate(&self) {\n        if self.terminate_count.fetch_sub(1, Ordering::AcqRel) == 1 {\n            for (i, thread_info) in self.thread_infos.iter().enumerate() {\n                unsafe { OnceLatch::set_and_tickle_one(&thread_info.terminate, self, i) };\n            }\n        }\n    }\n\n    /// Notify the worker that the latch they are sleeping on has been \"set\".\n    pub(super) fn notify_worker_latch_is_set(&self, target_worker_index: usize) {\n        self.sleep.notify_worker_latch_is_set(target_worker_index);\n    }\n}\n\n#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]\npub(super) struct RegistryId {\n    addr: usize,\n}\n\nstruct ThreadInfo {\n    /// Latch set once thread has started and we are entering into the\n    /// main loop. Used to wait for worker threads to become primed,\n    /// primarily of interest for benchmarking.\n    primed: LockLatch,\n\n    /// Latch is set once worker thread has completed. Used to wait\n    /// until workers have stopped; only used for tests.\n    stopped: LockLatch,\n\n    /// The latch used to signal that terminated has been requested.\n    /// This latch is *set* by the `terminate` method on the\n    /// `Registry`, once the registry's main \"terminate\" counter\n    /// reaches zero.\n    terminate: OnceLatch,\n\n    /// the \"stealer\" half of the worker's deque\n    stealer: Stealer<JobRef>,\n}\n\nimpl ThreadInfo {\n    fn new(stealer: Stealer<JobRef>) -> ThreadInfo {\n        ThreadInfo {\n            primed: LockLatch::new(),\n            stopped: LockLatch::new(),\n            terminate: OnceLatch::new(),\n            stealer,\n        }\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// WorkerThread identifiers\n\npub(super) struct WorkerThread {\n    /// the \"worker\" half of our local deque\n    worker: Worker<JobRef>,\n\n    /// the \"stealer\" half of the worker's broadcast deque\n    stealer: Stealer<JobRef>,\n\n    /// local queue used for `spawn_fifo` indirection\n    fifo: JobFifo,\n\n    index: usize,\n\n    /// A weak random number generator.\n    rng: XorShift64Star,\n\n    registry: Arc<Registry>,\n}\n\n// This is a bit sketchy, but basically: the WorkerThread is\n// allocated on the stack of the worker on entry and stored into this\n// thread-local variable. So it will remain valid at least until the\n// worker is fully unwound. Using an unsafe pointer avoids the need\n// for a RefCell<T> etc.\nthread_local! {\n    static WORKER_THREAD_STATE: Cell<*const WorkerThread> = const { Cell::new(ptr::null()) };\n}\n\nimpl From<ThreadBuilder> for WorkerThread {\n    fn from(thread: ThreadBuilder) -> Self {\n        Self {\n            worker: thread.worker,\n            stealer: thread.stealer,\n            fifo: JobFifo::new(),\n            index: thread.index,\n            rng: XorShift64Star::new(),\n            registry: thread.registry,\n        }\n    }\n}\n\nimpl Drop for WorkerThread {\n    fn drop(&mut self) {\n        // Undo `set_current`\n        WORKER_THREAD_STATE.with(|t| {\n            assert!(t.get().eq(&(self as *const _)));\n            t.set(ptr::null());\n        });\n    }\n}\n\nimpl WorkerThread {\n    /// Gets the `WorkerThread` index for the current thread; returns\n    /// NULL if this is not a worker thread. This pointer is valid\n    /// anywhere on the current thread.\n    #[inline]\n    pub(super) fn current() -> *const WorkerThread {\n        WORKER_THREAD_STATE.get()\n    }\n\n    /// Sets `self` as the worker-thread index for the current thread.\n    /// This is done during worker-thread startup.\n    unsafe fn set_current(thread: *const WorkerThread) {\n        WORKER_THREAD_STATE.with(|t| {\n            assert!(t.get().is_null());\n            t.set(thread);\n        });\n    }\n\n    /// Returns the registry that owns this worker thread.\n    #[inline]\n    pub(super) fn registry(&self) -> &Arc<Registry> {\n        &self.registry\n    }\n\n    /// Our index amongst the worker threads (ranges from `0..self.num_threads()`).\n    #[inline]\n    pub(super) fn index(&self) -> usize {\n        self.index\n    }\n\n    #[inline]\n    pub(super) unsafe fn push(&self, job: JobRef) {\n        let queue_was_empty = self.worker.is_empty();\n        self.worker.push(job);\n        self.registry.sleep.new_internal_jobs(1, queue_was_empty);\n    }\n\n    #[inline]\n    pub(super) unsafe fn push_fifo(&self, job: JobRef) {\n        self.push(self.fifo.push(job));\n    }\n\n    #[inline]\n    pub(super) fn local_deque_is_empty(&self) -> bool {\n        self.worker.is_empty()\n    }\n\n    /// Attempts to obtain a \"local\" job -- typically this means\n    /// popping from the top of the stack, though if we are configured\n    /// for breadth-first execution, it would mean dequeuing from the\n    /// bottom.\n    #[inline]\n    pub(super) fn take_local_job(&self) -> Option<JobRef> {\n        let popped_job = self.worker.pop();\n\n        if popped_job.is_some() {\n            return popped_job;\n        }\n\n        loop {\n            match self.stealer.steal() {\n                Steal::Success(job) => return Some(job),\n                Steal::Empty => return None,\n                Steal::Retry => {}\n            }\n        }\n    }\n\n    fn has_injected_job(&self) -> bool {\n        !self.stealer.is_empty() || self.registry.has_injected_job()\n    }\n\n    /// Wait until the latch is set. Try to keep busy by popping and\n    /// stealing tasks as necessary.\n    #[inline]\n    pub(super) unsafe fn wait_until<L: AsCoreLatch + ?Sized>(&self, latch: &L) {\n        let latch = latch.as_core_latch();\n        if !latch.probe() {\n            self.wait_until_cold(latch);\n        }\n    }\n\n    #[cold]\n    unsafe fn wait_until_cold(&self, latch: &CoreLatch) {\n        // the code below should swallow all panics and hence never\n        // unwind; but if something does wrong, we want to abort,\n        // because otherwise other code in rayon may assume that the\n        // latch has been signaled, and that can lead to random memory\n        // accesses, which would be *very bad*\n        let abort_guard = unwind::AbortIfPanic;\n\n        'outer: while !latch.probe() {\n            // Check for local work *before* we start marking ourself idle,\n            // especially to avoid modifying shared sleep state.\n            if let Some(job) = self.take_local_job() {\n                self.execute(job);\n                continue;\n            }\n\n            let mut idle_state = self.registry.sleep.start_looking(self.index);\n            while !latch.probe() {\n                if let Some(job) = self.find_work() {\n                    self.registry.sleep.work_found();\n                    self.execute(job);\n                    // The job might have injected local work, so go back to the outer loop.\n                    continue 'outer;\n                } else {\n                    self.registry\n                        .sleep\n                        .no_work_found(&mut idle_state, latch, || self.has_injected_job())\n                }\n            }\n\n            // If we were sleepy, we are not anymore. We \"found work\" --\n            // whatever the surrounding thread was doing before it had to wait.\n            self.registry.sleep.work_found();\n            break;\n        }\n\n        mem::forget(abort_guard); // successful execution, do not abort\n    }\n\n    unsafe fn wait_until_out_of_work(&self) {\n        debug_assert_eq!(self as *const _, WorkerThread::current());\n        let registry = &*self.registry;\n        let index = self.index;\n\n        self.wait_until(&registry.thread_infos[index].terminate);\n\n        // Should not be any work left in our queue.\n        debug_assert!(self.take_local_job().is_none());\n\n        // Let registry know we are done\n        Latch::set(&registry.thread_infos[index].stopped);\n    }\n\n    fn find_work(&self) -> Option<JobRef> {\n        // Try to find some work to do. We give preference first\n        // to things in our local deque, then in other workers\n        // deques, and finally to injected jobs from the\n        // outside. The idea is to finish what we started before\n        // we take on something new.\n        self.take_local_job()\n            .or_else(|| self.steal())\n            .or_else(|| self.registry.pop_injected_job())\n    }\n\n    pub(super) fn yield_now(&self) -> Yield {\n        match self.find_work() {\n            Some(job) => unsafe {\n                self.execute(job);\n                Yield::Executed\n            },\n            None => Yield::Idle,\n        }\n    }\n\n    pub(super) fn yield_local(&self) -> Yield {\n        match self.take_local_job() {\n            Some(job) => unsafe {\n                self.execute(job);\n                Yield::Executed\n            },\n            None => Yield::Idle,\n        }\n    }\n\n    #[inline]\n    pub(super) unsafe fn execute(&self, job: JobRef) {\n        job.execute();\n    }\n\n    /// Try to steal a single job and return it.\n    ///\n    /// This should only be done as a last resort, when there is no\n    /// local work to do.\n    fn steal(&self) -> Option<JobRef> {\n        // we only steal when we don't have any work to do locally\n        debug_assert!(self.local_deque_is_empty());\n\n        // otherwise, try to steal\n        let thread_infos = &self.registry.thread_infos.as_slice();\n        let num_threads = thread_infos.len();\n        if num_threads <= 1 {\n            return None;\n        }\n\n        loop {\n            let mut retry = false;\n            let start = self.rng.next_usize(num_threads);\n            let job = (start..num_threads)\n                .chain(0..start)\n                .filter(move |&i| i != self.index)\n                .find_map(|victim_index| {\n                    let victim = &thread_infos[victim_index];\n                    match victim.stealer.steal() {\n                        Steal::Success(job) => Some(job),\n                        Steal::Empty => None,\n                        Steal::Retry => {\n                            retry = true;\n                            None\n                        }\n                    }\n                });\n            if job.is_some() || !retry {\n                return job;\n            }\n        }\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n\nunsafe fn main_loop(thread: ThreadBuilder) {\n    let worker_thread = &WorkerThread::from(thread);\n    WorkerThread::set_current(worker_thread);\n    let registry = &*worker_thread.registry;\n    let index = worker_thread.index;\n\n    // let registry know we are ready to do work\n    Latch::set(&registry.thread_infos[index].primed);\n\n    // Worker threads should not panic. If they do, just abort, as the\n    // internal state of the thread pool is corrupted. Note that if\n    // **user code** panics, we should catch that and redirect.\n    let abort_guard = unwind::AbortIfPanic;\n\n    // Inform a user callback that we started a thread.\n    if let Some(ref handler) = registry.start_handler {\n        registry.catch_unwind(|| handler(index));\n    }\n\n    worker_thread.wait_until_out_of_work();\n\n    // Normal termination, do not abort.\n    mem::forget(abort_guard);\n\n    // Inform a user callback that we exited a thread.\n    if let Some(ref handler) = registry.exit_handler {\n        registry.catch_unwind(|| handler(index));\n        // We're already exiting the thread, there's nothing else to do.\n    }\n}\n\n/// If already in a worker-thread, just execute `op`.  Otherwise,\n/// execute `op` in the default thread pool. Either way, block until\n/// `op` completes and return its return value. If `op` panics, that\n/// panic will be propagated as well.  The second argument indicates\n/// `true` if injection was performed, `false` if executed directly.\npub(super) fn in_worker<OP, R>(op: OP) -> R\nwhere\n    OP: FnOnce(&WorkerThread, bool) -> R + Send,\n    R: Send,\n{\n    unsafe {\n        let owner_thread = WorkerThread::current();\n        if !owner_thread.is_null() {\n            // Perfectly valid to give them a `&T`: this is the\n            // current thread, so we know the data structure won't be\n            // invalidated until we return.\n            op(&*owner_thread, false)\n        } else {\n            global_registry().in_worker(op)\n        }\n    }\n}\n\n/// [xorshift*] is a fast pseudorandom number generator which will\n/// even tolerate weak seeding, as long as it's not zero.\n///\n/// [xorshift*]: https://en.wikipedia.org/wiki/Xorshift#xorshift*\nstruct XorShift64Star {\n    state: Cell<u64>,\n}\n\nimpl XorShift64Star {\n    fn new() -> Self {\n        // Any non-zero seed will do -- this uses the hash of a global counter.\n        let mut seed = 0;\n        while seed == 0 {\n            let mut hasher = DefaultHasher::new();\n            static COUNTER: AtomicUsize = AtomicUsize::new(0);\n            hasher.write_usize(COUNTER.fetch_add(1, Ordering::Relaxed));\n            seed = hasher.finish();\n        }\n\n        XorShift64Star {\n            state: Cell::new(seed),\n        }\n    }\n\n    fn next(&self) -> u64 {\n        let mut x = self.state.get();\n        debug_assert_ne!(x, 0);\n        x ^= x >> 12;\n        x ^= x << 25;\n        x ^= x >> 27;\n        self.state.set(x);\n        x.wrapping_mul(0x2545_f491_4f6c_dd1d)\n    }\n\n    /// Return a value from `0..n`.\n    fn next_usize(&self, n: usize) -> usize {\n        (self.next() % n as u64) as usize\n    }\n}\n"
  },
  {
    "path": "rayon-core/src/scope/mod.rs",
    "content": "//! Methods for custom fork-join scopes, created by the [`scope()`]\n//! and [`in_place_scope()`] functions. These are a more flexible alternative to [`join()`].\n//!\n//! [`join()`]: crate::join()\n\nuse crate::broadcast::BroadcastContext;\nuse crate::job::{ArcJob, HeapJob, JobFifo, JobRef};\nuse crate::latch::{CountLatch, Latch};\nuse crate::registry::{global_registry, in_worker, Registry, WorkerThread};\nuse crate::unwind;\nuse std::any::Any;\nuse std::fmt;\nuse std::marker::PhantomData;\nuse std::mem::ManuallyDrop;\nuse std::ptr;\nuse std::sync::atomic::{AtomicPtr, Ordering};\nuse std::sync::Arc;\n\n#[cfg(test)]\nmod test;\n\n/// Represents a fork-join scope which can be used to spawn any number of tasks.\n/// See [`scope()`] for more information.\npub struct Scope<'scope> {\n    base: ScopeBase<'scope>,\n}\n\n/// Represents a fork-join scope which can be used to spawn any number of tasks.\n/// Those spawned from the same thread are prioritized in relative FIFO order.\n/// See [`scope_fifo()`] for more information.\npub struct ScopeFifo<'scope> {\n    base: ScopeBase<'scope>,\n    fifos: Vec<JobFifo>,\n}\n\nstruct ScopeBase<'scope> {\n    /// thread registry where `scope()` was executed or where `in_place_scope()`\n    /// should spawn jobs.\n    registry: Arc<Registry>,\n\n    /// if some job panicked, the error is stored here; it will be\n    /// propagated to the one who created the scope\n    panic: AtomicPtr<Box<dyn Any + Send + 'static>>,\n\n    /// latch to track job counts\n    job_completed_latch: CountLatch,\n\n    /// You can think of a scope as containing a list of closures to execute,\n    /// all of which outlive `'scope`.  They're not actually required to be\n    /// `Sync`, but it's still safe to let the `Scope` implement `Sync` because\n    /// the closures are only *moved* across threads to be executed.\n    #[allow(clippy::type_complexity)]\n    marker: PhantomData<Box<dyn FnOnce(&Scope<'scope>) + Send + Sync + 'scope>>,\n}\n\n/// Creates a \"fork-join\" scope `s` and invokes the closure with a\n/// reference to `s`. This closure can then spawn asynchronous tasks\n/// into `s`. Those tasks may run asynchronously with respect to the\n/// closure; they may themselves spawn additional tasks into `s`. When\n/// the closure returns, it will block until all tasks that have been\n/// spawned into `s` complete.\n///\n/// `scope()` is a more flexible building block compared to `join()`,\n/// since a loop can be used to spawn any number of tasks without\n/// recursing. However, that flexibility comes at a performance price:\n/// tasks spawned using `scope()` must be allocated onto the heap,\n/// whereas `join()` can make exclusive use of the stack. **Prefer\n/// `join()` (or, even better, parallel iterators) where possible.**\n///\n/// # Example\n///\n/// The Rayon `join()` function launches two closures and waits for them\n/// to stop. One could implement `join()` using a scope like so, although\n/// it would be less efficient than the real implementation:\n///\n/// ```rust\n/// # use rayon_core as rayon;\n/// pub fn join<A,B,RA,RB>(oper_a: A, oper_b: B) -> (RA, RB)\n///     where A: FnOnce() -> RA + Send,\n///           B: FnOnce() -> RB + Send,\n///           RA: Send,\n///           RB: Send,\n/// {\n///     let mut result_a: Option<RA> = None;\n///     let mut result_b: Option<RB> = None;\n///     rayon::scope(|s| {\n///         s.spawn(|_| result_a = Some(oper_a()));\n///         s.spawn(|_| result_b = Some(oper_b()));\n///     });\n///     (result_a.unwrap(), result_b.unwrap())\n/// }\n/// ```\n///\n/// # A note on threading\n///\n/// The closure given to `scope()` executes in the Rayon thread pool,\n/// as do those given to `spawn()`. This means that you can't access\n/// thread-local variables (well, you can, but they may have\n/// unexpected values).\n///\n/// # Task execution\n///\n/// Task execution potentially starts as soon as `spawn()` is called.\n/// The task will end sometime before `scope()` returns. Note that the\n/// *closure* given to scope may return much earlier. In general\n/// the lifetime of a scope created like `scope(body)` goes something like this:\n///\n/// - Scope begins when `scope(body)` is called\n/// - Scope body `body()` is invoked\n///     - Scope tasks may be spawned\n/// - Scope body returns\n/// - Scope tasks execute, possibly spawning more tasks\n/// - Once all tasks are done, scope ends and `scope()` returns\n///\n/// To see how and when tasks are joined, consider this example:\n///\n/// ```rust\n/// # use rayon_core as rayon;\n/// // point start\n/// rayon::scope(|s| {\n///     s.spawn(|s| { // task s.1\n///         s.spawn(|s| { // task s.1.1\n///             rayon::scope(|t| {\n///                 t.spawn(|_| ()); // task t.1\n///                 t.spawn(|_| ()); // task t.2\n///             });\n///         });\n///     });\n///     s.spawn(|s| { // task s.2\n///     });\n///     // point mid\n/// });\n/// // point end\n/// ```\n///\n/// The various tasks that are run will execute roughly like so:\n///\n/// ```notrust\n/// | (start)\n/// |\n/// | (scope `s` created)\n/// +-----------------------------------------------+ (task s.2)\n/// +-------+ (task s.1)                            |\n/// |       |                                       |\n/// |       +---+ (task s.1.1)                      |\n/// |       |   |                                   |\n/// |       |   | (scope `t` created)               |\n/// |       |   +----------------+ (task t.2)       |\n/// |       |   +---+ (task t.1) |                  |\n/// | (mid) |   |   |            |                  |\n/// :       |   + <-+------------+ (scope `t` ends) |\n/// :       |   |                                   |\n/// |<------+---+-----------------------------------+ (scope `s` ends)\n/// |\n/// | (end)\n/// ```\n///\n/// The point here is that everything spawned into scope `s` will\n/// terminate (at latest) at the same point -- right before the\n/// original call to `rayon::scope` returns. This includes new\n/// subtasks created by other subtasks (e.g., task `s.1.1`). If a new\n/// scope is created (such as `t`), the things spawned into that scope\n/// will be joined before that scope returns, which in turn occurs\n/// before the creating task (task `s.1.1` in this case) finishes.\n///\n/// There is no guaranteed order of execution for spawns in a scope,\n/// given that other threads may steal tasks at any time. However, they\n/// are generally prioritized in a LIFO order on the thread from which\n/// they were spawned. So in this example, absent any stealing, we can\n/// expect `s.2` to execute before `s.1`, and `t.2` before `t.1`. Other\n/// threads always steal from the other end of the deque, like FIFO\n/// order.  The idea is that \"recent\" tasks are most likely to be fresh\n/// in the local CPU's cache, while other threads can steal older\n/// \"stale\" tasks.  For an alternate approach, consider\n/// [`scope_fifo()`] instead.\n///\n/// # Accessing stack data\n///\n/// In general, spawned tasks may access stack data in place that\n/// outlives the scope itself. Other data must be fully owned by the\n/// spawned task.\n///\n/// ```rust\n/// # use rayon_core as rayon;\n/// let ok: Vec<i32> = vec![1, 2, 3];\n/// rayon::scope(|s| {\n///     let bad: Vec<i32> = vec![4, 5, 6];\n///     s.spawn(|_| {\n///         // We can access `ok` because outlives the scope `s`.\n///         println!(\"ok: {:?}\", ok);\n///\n///         // If we just try to use `bad` here, the closure will borrow `bad`\n///         // (because we are just printing it out, and that only requires a\n///         // borrow), which will result in a compilation error. Read on\n///         // for options.\n///         // println!(\"bad: {:?}\", bad);\n///    });\n/// });\n/// ```\n///\n/// As the comments example above suggest, to reference `bad` we must\n/// take ownership of it. One way to do this is to detach the closure\n/// from the surrounding stack frame, using the `move` keyword. This\n/// will cause it to take ownership of *all* the variables it touches,\n/// in this case including both `ok` *and* `bad`:\n///\n/// ```rust\n/// # use rayon_core as rayon;\n/// let ok: Vec<i32> = vec![1, 2, 3];\n/// rayon::scope(|s| {\n///     let bad: Vec<i32> = vec![4, 5, 6];\n///     s.spawn(move |_| {\n///         println!(\"ok: {:?}\", ok);\n///         println!(\"bad: {:?}\", bad);\n///     });\n///\n///     // That closure is fine, but now we can't use `ok` anywhere else,\n///     // since it is owned by the previous task:\n///     // s.spawn(|_| println!(\"ok: {:?}\", ok));\n/// });\n/// ```\n///\n/// While this works, it could be a problem if we want to use `ok` elsewhere.\n/// There are two choices. We can keep the closure as a `move` closure, but\n/// instead of referencing the variable `ok`, we create a shadowed variable that\n/// is a borrow of `ok` and capture *that*:\n///\n/// ```rust\n/// # use rayon_core as rayon;\n/// let ok: Vec<i32> = vec![1, 2, 3];\n/// rayon::scope(|s| {\n///     let bad: Vec<i32> = vec![4, 5, 6];\n///     let ok: &Vec<i32> = &ok; // shadow the original `ok`\n///     s.spawn(move |_| {\n///         println!(\"ok: {:?}\", ok); // captures the shadowed version\n///         println!(\"bad: {:?}\", bad);\n///     });\n///\n///     // Now we too can use the shadowed `ok`, since `&Vec<i32>` references\n///     // can be shared freely. Note that we need a `move` closure here though,\n///     // because otherwise we'd be trying to borrow the shadowed `ok`,\n///     // and that doesn't outlive `scope`.\n///     s.spawn(move |_| println!(\"ok: {:?}\", ok));\n/// });\n/// ```\n///\n/// Another option is not to use the `move` keyword but instead to take ownership\n/// of individual variables:\n///\n/// ```rust\n/// # use rayon_core as rayon;\n/// let ok: Vec<i32> = vec![1, 2, 3];\n/// rayon::scope(|s| {\n///     let bad: Vec<i32> = vec![4, 5, 6];\n///     s.spawn(|_| {\n///         // Transfer ownership of `bad` into a local variable (also named `bad`).\n///         // This will force the closure to take ownership of `bad` from the environment.\n///         let bad = bad;\n///         println!(\"ok: {:?}\", ok); // `ok` is only borrowed.\n///         println!(\"bad: {:?}\", bad); // refers to our local variable, above.\n///     });\n///\n///     s.spawn(|_| println!(\"ok: {:?}\", ok)); // we too can borrow `ok`\n/// });\n/// ```\n///\n/// # Panics\n///\n/// If a panic occurs, either in the closure given to `scope()` or in\n/// any of the spawned jobs, that panic will be propagated and the\n/// call to `scope()` will panic. If multiple panics occurs, it is\n/// non-deterministic which of their panic values will propagate.\n/// Regardless, once a task is spawned using `scope.spawn()`, it will\n/// execute, even if the spawning task should later panic. `scope()`\n/// returns once all spawned jobs have completed, and any panics are\n/// propagated at that point.\npub fn scope<'scope, OP, R>(op: OP) -> R\nwhere\n    OP: FnOnce(&Scope<'scope>) -> R + Send,\n    R: Send,\n{\n    in_worker(|owner_thread, _| {\n        let scope = Scope::<'scope>::new(Some(owner_thread), None);\n        scope.base.complete(Some(owner_thread), || op(&scope))\n    })\n}\n\n/// Creates a \"fork-join\" scope `s` with FIFO order, and invokes the\n/// closure with a reference to `s`. This closure can then spawn\n/// asynchronous tasks into `s`. Those tasks may run asynchronously with\n/// respect to the closure; they may themselves spawn additional tasks\n/// into `s`. When the closure returns, it will block until all tasks\n/// that have been spawned into `s` complete.\n///\n/// # Task execution\n///\n/// Tasks in a `scope_fifo()` run similarly to [`scope()`], but there's a\n/// difference in the order of execution. Consider a similar example:\n///\n/// ```rust\n/// # use rayon_core as rayon;\n/// // point start\n/// rayon::scope_fifo(|s| {\n///     s.spawn_fifo(|s| { // task s.1\n///         s.spawn_fifo(|s| { // task s.1.1\n///             rayon::scope_fifo(|t| {\n///                 t.spawn_fifo(|_| ()); // task t.1\n///                 t.spawn_fifo(|_| ()); // task t.2\n///             });\n///         });\n///     });\n///     s.spawn_fifo(|s| { // task s.2\n///     });\n///     // point mid\n/// });\n/// // point end\n/// ```\n///\n/// The various tasks that are run will execute roughly like so:\n///\n/// ```notrust\n/// | (start)\n/// |\n/// | (FIFO scope `s` created)\n/// +--------------------+ (task s.1)\n/// +-------+ (task s.2) |\n/// |       |            +---+ (task s.1.1)\n/// |       |            |   |\n/// |       |            |   | (FIFO scope `t` created)\n/// |       |            |   +----------------+ (task t.1)\n/// |       |            |   +---+ (task t.2) |\n/// | (mid) |            |   |   |            |\n/// :       |            |   + <-+------------+ (scope `t` ends)\n/// :       |            |   |\n/// |<------+------------+---+ (scope `s` ends)\n/// |\n/// | (end)\n/// ```\n///\n/// Under `scope_fifo()`, the spawns are prioritized in a FIFO order on\n/// the thread from which they were spawned, as opposed to `scope()`'s\n/// LIFO.  So in this example, we can expect `s.1` to execute before\n/// `s.2`, and `t.1` before `t.2`. Other threads also steal tasks in\n/// FIFO order, as usual. Overall, this has roughly the same order as\n/// the now-deprecated [`breadth_first`] option, except the effect is\n/// isolated to a particular scope. If spawns are intermingled from any\n/// combination of `scope()` and `scope_fifo()`, or from different\n/// threads, their order is only specified with respect to spawns in the\n/// same scope and thread.\n///\n/// For more details on this design, see Rayon [RFC #1].\n///\n/// [`breadth_first`]: crate::ThreadPoolBuilder::breadth_first\n/// [RFC #1]: https://github.com/rayon-rs/rfcs/blob/main/accepted/rfc0001-scope-scheduling.md\n///\n/// # Panics\n///\n/// If a panic occurs, either in the closure given to `scope_fifo()` or\n/// in any of the spawned jobs, that panic will be propagated and the\n/// call to `scope_fifo()` will panic. If multiple panics occurs, it is\n/// non-deterministic which of their panic values will propagate.\n/// Regardless, once a task is spawned using `scope.spawn_fifo()`, it\n/// will execute, even if the spawning task should later panic.\n/// `scope_fifo()` returns once all spawned jobs have completed, and any\n/// panics are propagated at that point.\npub fn scope_fifo<'scope, OP, R>(op: OP) -> R\nwhere\n    OP: FnOnce(&ScopeFifo<'scope>) -> R + Send,\n    R: Send,\n{\n    in_worker(|owner_thread, _| {\n        let scope = ScopeFifo::<'scope>::new(Some(owner_thread), None);\n        scope.base.complete(Some(owner_thread), || op(&scope))\n    })\n}\n\n/// Creates a \"fork-join\" scope `s` and invokes the closure with a\n/// reference to `s`. This closure can then spawn asynchronous tasks\n/// into `s`. Those tasks may run asynchronously with respect to the\n/// closure; they may themselves spawn additional tasks into `s`. When\n/// the closure returns, it will block until all tasks that have been\n/// spawned into `s` complete.\n///\n/// This is just like `scope()` except the closure runs on the same thread\n/// that calls `in_place_scope()`. Only work that it spawns runs in the\n/// thread pool.\n///\n/// # Panics\n///\n/// If a panic occurs, either in the closure given to `in_place_scope()` or in\n/// any of the spawned jobs, that panic will be propagated and the\n/// call to `in_place_scope()` will panic. If multiple panics occurs, it is\n/// non-deterministic which of their panic values will propagate.\n/// Regardless, once a task is spawned using `scope.spawn()`, it will\n/// execute, even if the spawning task should later panic. `in_place_scope()`\n/// returns once all spawned jobs have completed, and any panics are\n/// propagated at that point.\npub fn in_place_scope<'scope, OP, R>(op: OP) -> R\nwhere\n    OP: FnOnce(&Scope<'scope>) -> R,\n{\n    do_in_place_scope(None, op)\n}\n\npub(crate) fn do_in_place_scope<'scope, OP, R>(registry: Option<&Arc<Registry>>, op: OP) -> R\nwhere\n    OP: FnOnce(&Scope<'scope>) -> R,\n{\n    let (thread, registry) = get_in_place_thread_registry(registry);\n    let scope = Scope::<'scope>::new(thread, registry);\n    scope.base.complete(thread, || op(&scope))\n}\n\nfn get_in_place_thread_registry(\n    registry: Option<&Arc<Registry>>,\n) -> (Option<&WorkerThread>, Option<&Arc<Registry>>) {\n    let thread = unsafe { WorkerThread::current().as_ref() };\n    if thread.is_none() && registry.is_none() {\n        // A new global registry may use the current thread, especially on WebAssembly,\n        // so we have to re-check our current status after it's built.\n        let global = global_registry();\n        (global.current_thread(), Some(global))\n    } else {\n        (thread, registry)\n    }\n}\n\n/// Creates a \"fork-join\" scope `s` with FIFO order, and invokes the\n/// closure with a reference to `s`. This closure can then spawn\n/// asynchronous tasks into `s`. Those tasks may run asynchronously with\n/// respect to the closure; they may themselves spawn additional tasks\n/// into `s`. When the closure returns, it will block until all tasks\n/// that have been spawned into `s` complete.\n///\n/// This is just like `scope_fifo()` except the closure runs on the same thread\n/// that calls `in_place_scope_fifo()`. Only work that it spawns runs in the\n/// thread pool.\n///\n/// # Panics\n///\n/// If a panic occurs, either in the closure given to `in_place_scope_fifo()` or in\n/// any of the spawned jobs, that panic will be propagated and the\n/// call to `in_place_scope_fifo()` will panic. If multiple panics occurs, it is\n/// non-deterministic which of their panic values will propagate.\n/// Regardless, once a task is spawned using `scope.spawn_fifo()`, it will\n/// execute, even if the spawning task should later panic. `in_place_scope_fifo()`\n/// returns once all spawned jobs have completed, and any panics are\n/// propagated at that point.\npub fn in_place_scope_fifo<'scope, OP, R>(op: OP) -> R\nwhere\n    OP: FnOnce(&ScopeFifo<'scope>) -> R,\n{\n    do_in_place_scope_fifo(None, op)\n}\n\npub(crate) fn do_in_place_scope_fifo<'scope, OP, R>(registry: Option<&Arc<Registry>>, op: OP) -> R\nwhere\n    OP: FnOnce(&ScopeFifo<'scope>) -> R,\n{\n    let (thread, registry) = get_in_place_thread_registry(registry);\n    let scope = ScopeFifo::<'scope>::new(thread, registry);\n    scope.base.complete(thread, || op(&scope))\n}\n\nimpl<'scope> Scope<'scope> {\n    fn new(owner: Option<&WorkerThread>, registry: Option<&Arc<Registry>>) -> Self {\n        let base = ScopeBase::new(owner, registry);\n        Scope { base }\n    }\n\n    /// Spawns a job into the fork-join scope `self`. This job will\n    /// execute sometime before the fork-join scope completes.  The\n    /// job is specified as a closure, and this closure receives its\n    /// own reference to the scope `self` as argument. This can be\n    /// used to inject new jobs into `self`.\n    ///\n    /// # Returns\n    ///\n    /// Nothing. The spawned closures cannot pass back values to the\n    /// caller directly, though they can write to local variables on\n    /// the stack (if those variables outlive the scope) or\n    /// communicate through shared channels.\n    ///\n    /// (The intention is to eventually integrate with Rust futures to\n    /// support spawns of functions that compute a value.)\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// # use rayon_core as rayon;\n    /// let mut value_a = None;\n    /// let mut value_b = None;\n    /// let mut value_c = None;\n    /// rayon::scope(|s| {\n    ///     s.spawn(|s1| {\n    ///           // ^ this is the same scope as `s`; this handle `s1`\n    ///           //   is intended for use by the spawned task,\n    ///           //   since scope handles cannot cross thread boundaries.\n    ///\n    ///         value_a = Some(22);\n    ///\n    ///         // the scope `s` will not end until all these tasks are done\n    ///         s1.spawn(|_| {\n    ///             value_b = Some(44);\n    ///         });\n    ///     });\n    ///\n    ///     s.spawn(|_| {\n    ///         value_c = Some(66);\n    ///     });\n    /// });\n    /// assert_eq!(value_a, Some(22));\n    /// assert_eq!(value_b, Some(44));\n    /// assert_eq!(value_c, Some(66));\n    /// ```\n    ///\n    /// # See also\n    ///\n    /// The [`scope` function] has more extensive documentation about\n    /// task spawning.\n    ///\n    /// [`scope` function]: scope()\n    pub fn spawn<BODY>(&self, body: BODY)\n    where\n        BODY: FnOnce(&Scope<'scope>) + Send + 'scope,\n    {\n        let scope_ptr = ScopePtr(self);\n        let job = HeapJob::new(move || unsafe {\n            // SAFETY: this job will execute before the scope ends.\n            let scope = scope_ptr.as_ref();\n            ScopeBase::execute_job(&scope.base, move || body(scope))\n        });\n        let job_ref = self.base.heap_job_ref(job);\n\n        // Since `Scope` implements `Sync`, we can't be sure that we're still in a\n        // thread of this pool, so we can't just push to the local worker thread.\n        // Also, this might be an in-place scope.\n        self.base.registry.inject_or_push(job_ref);\n    }\n\n    /// Spawns a job into every thread of the fork-join scope `self`. This job will\n    /// execute on each thread sometime before the fork-join scope completes.  The\n    /// job is specified as a closure, and this closure receives its own reference\n    /// to the scope `self` as argument, as well as a `BroadcastContext`.\n    pub fn spawn_broadcast<BODY>(&self, body: BODY)\n    where\n        BODY: Fn(&Scope<'scope>, BroadcastContext<'_>) + Send + Sync + 'scope,\n    {\n        let scope_ptr = ScopePtr(self);\n        let job = ArcJob::new(move || unsafe {\n            // SAFETY: this job will execute before the scope ends.\n            let scope = scope_ptr.as_ref();\n            let body = &body;\n            let func = move || BroadcastContext::with(move |ctx| body(scope, ctx));\n            ScopeBase::execute_job(&scope.base, func)\n        });\n        self.base.inject_broadcast(job)\n    }\n}\n\nimpl<'scope> ScopeFifo<'scope> {\n    fn new(owner: Option<&WorkerThread>, registry: Option<&Arc<Registry>>) -> Self {\n        let base = ScopeBase::new(owner, registry);\n        let num_threads = base.registry.num_threads();\n        let fifos = (0..num_threads).map(|_| JobFifo::new()).collect();\n        ScopeFifo { base, fifos }\n    }\n\n    /// Spawns a job into the fork-join scope `self`. This job will\n    /// execute sometime before the fork-join scope completes.  The\n    /// job is specified as a closure, and this closure receives its\n    /// own reference to the scope `self` as argument. This can be\n    /// used to inject new jobs into `self`.\n    ///\n    /// # See also\n    ///\n    /// This method is akin to [`Scope::spawn()`], but with a FIFO\n    /// priority.  The [`scope_fifo` function] has more details about\n    /// this distinction.\n    ///\n    /// [`scope_fifo` function]: scope_fifo()\n    pub fn spawn_fifo<BODY>(&self, body: BODY)\n    where\n        BODY: FnOnce(&ScopeFifo<'scope>) + Send + 'scope,\n    {\n        let scope_ptr = ScopePtr(self);\n        let job = HeapJob::new(move || unsafe {\n            // SAFETY: this job will execute before the scope ends.\n            let scope = scope_ptr.as_ref();\n            ScopeBase::execute_job(&scope.base, move || body(scope))\n        });\n        let job_ref = self.base.heap_job_ref(job);\n\n        // If we're in the pool, use our scope's private fifo for this thread to execute\n        // in a locally-FIFO order. Otherwise, just use the pool's global injector.\n        match self.base.registry.current_thread() {\n            Some(worker) => {\n                let fifo = &self.fifos[worker.index()];\n                // SAFETY: this job will execute before the scope ends.\n                unsafe { worker.push(fifo.push(job_ref)) };\n            }\n            None => self.base.registry.inject(job_ref),\n        }\n    }\n\n    /// Spawns a job into every thread of the fork-join scope `self`. This job will\n    /// execute on each thread sometime before the fork-join scope completes.  The\n    /// job is specified as a closure, and this closure receives its own reference\n    /// to the scope `self` as argument, as well as a `BroadcastContext`.\n    pub fn spawn_broadcast<BODY>(&self, body: BODY)\n    where\n        BODY: Fn(&ScopeFifo<'scope>, BroadcastContext<'_>) + Send + Sync + 'scope,\n    {\n        let scope_ptr = ScopePtr(self);\n        let job = ArcJob::new(move || unsafe {\n            // SAFETY: this job will execute before the scope ends.\n            let scope = scope_ptr.as_ref();\n            let body = &body;\n            let func = move || BroadcastContext::with(move |ctx| body(scope, ctx));\n            ScopeBase::execute_job(&scope.base, func)\n        });\n        self.base.inject_broadcast(job)\n    }\n}\n\nimpl<'scope> ScopeBase<'scope> {\n    /// Creates the base of a new scope for the given registry\n    fn new(owner: Option<&WorkerThread>, registry: Option<&Arc<Registry>>) -> Self {\n        let registry = registry.unwrap_or_else(|| match owner {\n            Some(owner) => owner.registry(),\n            None => global_registry(),\n        });\n\n        ScopeBase {\n            registry: Arc::clone(registry),\n            panic: AtomicPtr::new(ptr::null_mut()),\n            job_completed_latch: CountLatch::new(owner),\n            marker: PhantomData,\n        }\n    }\n\n    fn heap_job_ref<FUNC>(&self, job: Box<HeapJob<FUNC>>) -> JobRef\n    where\n        FUNC: FnOnce() + Send + 'scope,\n    {\n        unsafe {\n            self.job_completed_latch.increment();\n            job.into_job_ref()\n        }\n    }\n\n    fn inject_broadcast<FUNC>(&self, job: Arc<ArcJob<FUNC>>)\n    where\n        FUNC: Fn() + Send + Sync + 'scope,\n    {\n        let n_threads = self.registry.num_threads();\n        let job_refs = (0..n_threads).map(|_| unsafe {\n            self.job_completed_latch.increment();\n            ArcJob::as_job_ref(&job)\n        });\n\n        self.registry.inject_broadcast(job_refs);\n    }\n\n    /// Executes `func` as a job, either aborting or executing as\n    /// appropriate.\n    fn complete<FUNC, R>(&self, owner: Option<&WorkerThread>, func: FUNC) -> R\n    where\n        FUNC: FnOnce() -> R,\n    {\n        let result = unsafe { Self::execute_job_closure(self, func) };\n        self.job_completed_latch.wait(owner);\n        self.maybe_propagate_panic();\n        result.unwrap() // only None if `op` panicked, and that would have been propagated\n    }\n\n    /// Executes `func` as a job, either aborting or executing as\n    /// appropriate.\n    unsafe fn execute_job<FUNC>(this: *const Self, func: FUNC)\n    where\n        FUNC: FnOnce(),\n    {\n        let _: Option<()> = Self::execute_job_closure(this, func);\n    }\n\n    /// Executes `func` as a job in scope. Adjusts the \"job completed\"\n    /// counters and also catches any panic and stores it into\n    /// `scope`.\n    unsafe fn execute_job_closure<FUNC, R>(this: *const Self, func: FUNC) -> Option<R>\n    where\n        FUNC: FnOnce() -> R,\n    {\n        let result = match unwind::halt_unwinding(func) {\n            Ok(r) => Some(r),\n            Err(err) => {\n                (*this).job_panicked(err);\n                None\n            }\n        };\n        Latch::set(&(*this).job_completed_latch);\n        result\n    }\n\n    fn job_panicked(&self, err: Box<dyn Any + Send + 'static>) {\n        // capture the first error we see, free the rest\n        if self.panic.load(Ordering::Relaxed).is_null() {\n            let nil = ptr::null_mut();\n            let mut err = ManuallyDrop::new(Box::new(err)); // box up the fat ptr\n            let err_ptr: *mut Box<dyn Any + Send + 'static> = &mut **err;\n            if self\n                .panic\n                .compare_exchange(nil, err_ptr, Ordering::Release, Ordering::Relaxed)\n                .is_ok()\n            {\n                // ownership now transferred into self.panic\n            } else {\n                // another panic raced in ahead of us, so drop ours\n                let _: Box<Box<_>> = ManuallyDrop::into_inner(err);\n            }\n        }\n    }\n\n    fn maybe_propagate_panic(&self) {\n        // propagate panic, if any occurred; at this point, all\n        // outstanding jobs have completed, so we can use a relaxed\n        // ordering:\n        let panic = self.panic.swap(ptr::null_mut(), Ordering::Relaxed);\n        if !panic.is_null() {\n            let value = unsafe { Box::from_raw(panic) };\n            unwind::resume_unwinding(*value);\n        }\n    }\n}\n\nimpl<'scope> fmt::Debug for Scope<'scope> {\n    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt.debug_struct(\"Scope\")\n            .field(\"pool_id\", &self.base.registry.id())\n            .field(\"panic\", &self.base.panic)\n            .field(\"job_completed_latch\", &self.base.job_completed_latch)\n            .finish()\n    }\n}\n\nimpl<'scope> fmt::Debug for ScopeFifo<'scope> {\n    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt.debug_struct(\"ScopeFifo\")\n            .field(\"num_fifos\", &self.fifos.len())\n            .field(\"pool_id\", &self.base.registry.id())\n            .field(\"panic\", &self.base.panic)\n            .field(\"job_completed_latch\", &self.base.job_completed_latch)\n            .finish()\n    }\n}\n\n/// Used to capture a scope `&Self` pointer in jobs, without faking a lifetime.\n///\n/// Unsafe code is still required to dereference the pointer, but that's fine in\n/// scope jobs that are guaranteed to execute before the scope ends.\nstruct ScopePtr<T>(*const T);\n\n// SAFETY: !Send for raw pointers is not for safety, just as a lint\nunsafe impl<T: Sync> Send for ScopePtr<T> {}\n\n// SAFETY: !Sync for raw pointers is not for safety, just as a lint\nunsafe impl<T: Sync> Sync for ScopePtr<T> {}\n\nimpl<T> ScopePtr<T> {\n    // Helper to avoid disjoint captures of `scope_ptr.0`\n    unsafe fn as_ref(&self) -> &T {\n        &*self.0\n    }\n}\n"
  },
  {
    "path": "rayon-core/src/scope/test.rs",
    "content": "use crate::unwind;\nuse crate::ThreadPoolBuilder;\nuse crate::{scope, scope_fifo, Scope, ScopeFifo};\nuse rand::{Rng, SeedableRng};\nuse rand_xorshift::XorShiftRng;\nuse std::iter::once;\nuse std::sync::atomic::{AtomicUsize, Ordering};\nuse std::sync::{Barrier, Mutex};\nuse std::vec;\n\n#[test]\nfn scope_empty() {\n    scope(|_| {});\n}\n\n#[test]\nfn scope_result() {\n    let x = scope(|_| 22);\n    assert_eq!(x, 22);\n}\n\n#[test]\nfn scope_two() {\n    let counter = &AtomicUsize::new(0);\n    scope(|s| {\n        s.spawn(move |_| {\n            counter.fetch_add(1, Ordering::SeqCst);\n        });\n        s.spawn(move |_| {\n            counter.fetch_add(10, Ordering::SeqCst);\n        });\n    });\n\n    let v = counter.load(Ordering::SeqCst);\n    assert_eq!(v, 11);\n}\n\n#[test]\nfn scope_divide_and_conquer() {\n    let counter_p = &AtomicUsize::new(0);\n    scope(|s| s.spawn(move |s| divide_and_conquer(s, counter_p, 1024)));\n\n    let counter_s = &AtomicUsize::new(0);\n    divide_and_conquer_seq(counter_s, 1024);\n\n    let p = counter_p.load(Ordering::SeqCst);\n    let s = counter_s.load(Ordering::SeqCst);\n    assert_eq!(p, s);\n}\n\nfn divide_and_conquer<'scope>(scope: &Scope<'scope>, counter: &'scope AtomicUsize, size: usize) {\n    if size > 1 {\n        scope.spawn(move |scope| divide_and_conquer(scope, counter, size / 2));\n        scope.spawn(move |scope| divide_and_conquer(scope, counter, size / 2));\n    } else {\n        // count the leaves\n        counter.fetch_add(1, Ordering::SeqCst);\n    }\n}\n\nfn divide_and_conquer_seq(counter: &AtomicUsize, size: usize) {\n    if size > 1 {\n        divide_and_conquer_seq(counter, size / 2);\n        divide_and_conquer_seq(counter, size / 2);\n    } else {\n        // count the leaves\n        counter.fetch_add(1, Ordering::SeqCst);\n    }\n}\n\nstruct Tree<T: Send> {\n    value: T,\n    children: Vec<Tree<T>>,\n}\n\nimpl<T: Send> Tree<T> {\n    fn iter(&self) -> vec::IntoIter<&T> {\n        once(&self.value)\n            .chain(self.children.iter().flat_map(Tree::iter))\n            .collect::<Vec<_>>() // seems like it shouldn't be needed... but prevents overflow\n            .into_iter()\n    }\n\n    fn update<OP>(&mut self, op: OP)\n    where\n        OP: Fn(&mut T) + Sync,\n        T: Send,\n    {\n        scope(|s| self.update_in_scope(&op, s));\n    }\n\n    fn update_in_scope<'scope, OP>(&'scope mut self, op: &'scope OP, scope: &Scope<'scope>)\n    where\n        OP: Fn(&mut T) + Sync,\n    {\n        let Tree {\n            ref mut value,\n            ref mut children,\n        } = *self;\n        scope.spawn(move |scope| {\n            for child in children {\n                scope.spawn(move |scope| child.update_in_scope(op, scope));\n            }\n        });\n\n        op(value);\n    }\n}\n\nfn random_tree(depth: usize) -> Tree<u32> {\n    assert!(depth > 0);\n    let mut seed = <XorShiftRng as SeedableRng>::Seed::default();\n    (0..).zip(seed.as_mut()).for_each(|(i, x)| *x = i);\n    let mut rng = XorShiftRng::from_seed(seed);\n    random_tree1(depth, &mut rng)\n}\n\nfn random_tree1(depth: usize, rng: &mut XorShiftRng) -> Tree<u32> {\n    let children = if depth == 0 {\n        vec![]\n    } else {\n        (0..rng.random_range(0..4)) // somewhere between 0 and 3 children at each level\n            .map(|_| random_tree1(depth - 1, rng))\n            .collect()\n    };\n\n    Tree {\n        value: rng.random_range(0..1_000_000),\n        children,\n    }\n}\n\n#[test]\nfn update_tree() {\n    let mut tree: Tree<u32> = random_tree(10);\n    let values: Vec<u32> = tree.iter().cloned().collect();\n    tree.update(|v| *v += 1);\n    let new_values: Vec<u32> = tree.iter().cloned().collect();\n    assert_eq!(values.len(), new_values.len());\n    for (&i, &j) in values.iter().zip(&new_values) {\n        assert_eq!(i + 1, j);\n    }\n}\n\n/// Check that if you have a chain of scoped tasks where T0 spawns T1\n/// spawns T2 and so forth down to Tn, the stack space should not grow\n/// linearly with N. We test this by some unsafe hackery and\n/// permitting an approx 10% change with a 10x input change.\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn linear_stack_growth() {\n    let builder = ThreadPoolBuilder::new().num_threads(1);\n    let pool = builder.build().unwrap();\n    pool.install(|| {\n        let mut max_diff = Mutex::new(0);\n        let bottom_of_stack = 0;\n        scope(|s| the_final_countdown(s, &bottom_of_stack, &max_diff, 5));\n        let diff_when_5 = *max_diff.get_mut().unwrap() as f64;\n\n        scope(|s| the_final_countdown(s, &bottom_of_stack, &max_diff, 500));\n        let diff_when_500 = *max_diff.get_mut().unwrap() as f64;\n\n        let ratio = diff_when_5 / diff_when_500;\n        assert!(\n            ratio > 0.9 && ratio < 1.1,\n            \"stack usage ratio out of bounds: {ratio}\"\n        );\n    });\n}\n\nfn the_final_countdown<'scope>(\n    s: &Scope<'scope>,\n    bottom_of_stack: &'scope i32,\n    max: &'scope Mutex<usize>,\n    n: usize,\n) {\n    let top_of_stack = 0;\n    let p = bottom_of_stack as *const i32 as usize;\n    let q = &top_of_stack as *const i32 as usize;\n    let diff = p.abs_diff(q);\n\n    let mut data = max.lock().unwrap();\n    *data = Ord::max(diff, *data);\n\n    if n > 0 {\n        s.spawn(move |s| the_final_countdown(s, bottom_of_stack, max, n - 1));\n    }\n}\n\n#[test]\n#[should_panic(expected = \"Hello, world!\")]\nfn panic_propagate_scope() {\n    scope(|_| panic!(\"Hello, world!\"));\n}\n\n#[test]\n#[should_panic(expected = \"Hello, world!\")]\nfn panic_propagate_spawn() {\n    scope(|s| s.spawn(|_| panic!(\"Hello, world!\")));\n}\n\n#[test]\n#[should_panic(expected = \"Hello, world!\")]\nfn panic_propagate_nested_spawn() {\n    scope(|s| s.spawn(|s| s.spawn(|s| s.spawn(|_| panic!(\"Hello, world!\")))));\n}\n\n#[test]\n#[should_panic(expected = \"Hello, world!\")]\nfn panic_propagate_nested_scope_spawn() {\n    scope(|s| s.spawn(|_| scope(|s| s.spawn(|_| panic!(\"Hello, world!\")))));\n}\n\n#[test]\n#[cfg_attr(not(panic = \"unwind\"), ignore)]\nfn panic_propagate_still_execute_1() {\n    let mut x = false;\n    let result = unwind::halt_unwinding(|| {\n        scope(|s| {\n            s.spawn(|_| panic!(\"Hello, world!\")); // job A\n            s.spawn(|_| x = true); // job B, should still execute even though A panics\n        });\n    });\n    match result {\n        Ok(_) => panic!(\"failed to propagate panic\"),\n        Err(_) => assert!(x, \"job b failed to execute\"),\n    }\n}\n\n#[test]\n#[cfg_attr(not(panic = \"unwind\"), ignore)]\nfn panic_propagate_still_execute_2() {\n    let mut x = false;\n    let result = unwind::halt_unwinding(|| {\n        scope(|s| {\n            s.spawn(|_| x = true); // job B, should still execute even though A panics\n            s.spawn(|_| panic!(\"Hello, world!\")); // job A\n        });\n    });\n    match result {\n        Ok(_) => panic!(\"failed to propagate panic\"),\n        Err(_) => assert!(x, \"job b failed to execute\"),\n    }\n}\n\n#[test]\n#[cfg_attr(not(panic = \"unwind\"), ignore)]\nfn panic_propagate_still_execute_3() {\n    let mut x = false;\n    let result = unwind::halt_unwinding(|| {\n        scope(|s| {\n            s.spawn(|_| x = true); // spawned job should still execute despite later panic\n            panic!(\"Hello, world!\");\n        });\n    });\n    match result {\n        Ok(_) => panic!(\"failed to propagate panic\"),\n        Err(_) => assert!(x, \"panic after spawn, spawn failed to execute\"),\n    }\n}\n\n#[test]\n#[cfg_attr(not(panic = \"unwind\"), ignore)]\nfn panic_propagate_still_execute_4() {\n    let mut x = false;\n    let result = unwind::halt_unwinding(|| {\n        scope(|s| {\n            s.spawn(|_| panic!(\"Hello, world!\"));\n            x = true;\n        });\n    });\n    match result {\n        Ok(_) => panic!(\"failed to propagate panic\"),\n        Err(_) => assert!(x, \"panic in spawn tainted scope\"),\n    }\n}\n\nmacro_rules! test_order {\n    ($scope:ident => $spawn:ident) => {{\n        let builder = ThreadPoolBuilder::new().num_threads(1);\n        let pool = builder.build().unwrap();\n        pool.install(|| {\n            let vec = Mutex::new(vec![]);\n            $scope(|scope| {\n                let vec = &vec;\n                for i in 0..10 {\n                    scope.$spawn(move |scope| {\n                        for j in 0..10 {\n                            scope.$spawn(move |_| {\n                                vec.lock().unwrap().push(i * 10 + j);\n                            });\n                        }\n                    });\n                }\n            });\n            vec.into_inner().unwrap()\n        })\n    }};\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn lifo_order() {\n    // In the absence of stealing, `scope()` runs its `spawn()` jobs in LIFO order.\n    let vec = test_order!(scope => spawn);\n    let expected: Vec<i32> = (0..100).rev().collect(); // LIFO -> reversed\n    assert_eq!(vec, expected);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn fifo_order() {\n    // In the absence of stealing, `scope_fifo()` runs its `spawn_fifo()` jobs in FIFO order.\n    let vec = test_order!(scope_fifo => spawn_fifo);\n    let expected: Vec<i32> = (0..100).collect(); // FIFO -> natural order\n    assert_eq!(vec, expected);\n}\n\nmacro_rules! test_nested_order {\n    ($outer_scope:ident => $outer_spawn:ident,\n     $inner_scope:ident => $inner_spawn:ident) => {{\n        let builder = ThreadPoolBuilder::new().num_threads(1);\n        let pool = builder.build().unwrap();\n        pool.install(|| {\n            let vec = Mutex::new(vec![]);\n            $outer_scope(|scope| {\n                let vec = &vec;\n                for i in 0..10 {\n                    scope.$outer_spawn(move |_| {\n                        $inner_scope(|scope| {\n                            for j in 0..10 {\n                                scope.$inner_spawn(move |_| {\n                                    vec.lock().unwrap().push(i * 10 + j);\n                                });\n                            }\n                        });\n                    });\n                }\n            });\n            vec.into_inner().unwrap()\n        })\n    }};\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn nested_lifo_order() {\n    // In the absence of stealing, `scope()` runs its `spawn()` jobs in LIFO order.\n    let vec = test_nested_order!(scope => spawn, scope => spawn);\n    let expected: Vec<i32> = (0..100).rev().collect(); // LIFO -> reversed\n    assert_eq!(vec, expected);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn nested_fifo_order() {\n    // In the absence of stealing, `scope_fifo()` runs its `spawn_fifo()` jobs in FIFO order.\n    let vec = test_nested_order!(scope_fifo => spawn_fifo, scope_fifo => spawn_fifo);\n    let expected: Vec<i32> = (0..100).collect(); // FIFO -> natural order\n    assert_eq!(vec, expected);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn nested_lifo_fifo_order() {\n    // LIFO on the outside, FIFO on the inside\n    let vec = test_nested_order!(scope => spawn, scope_fifo => spawn_fifo);\n    let expected: Vec<i32> = (0..10)\n        .rev()\n        .flat_map(|i| (0..10).map(move |j| i * 10 + j))\n        .collect();\n    assert_eq!(vec, expected);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn nested_fifo_lifo_order() {\n    // FIFO on the outside, LIFO on the inside\n    let vec = test_nested_order!(scope_fifo => spawn_fifo, scope => spawn);\n    let expected: Vec<i32> = (0..10)\n        .flat_map(|i| (0..10).rev().map(move |j| i * 10 + j))\n        .collect();\n    assert_eq!(vec, expected);\n}\n\nmacro_rules! spawn_push {\n    ($scope:ident . $spawn:ident, $vec:ident, $i:expr) => {{\n        $scope.$spawn(move |_| $vec.lock().unwrap().push($i));\n    }};\n}\n\n/// Test spawns pushing a series of numbers, interleaved\n/// such that negative values are using an inner scope.\nmacro_rules! test_mixed_order {\n    ($outer_scope:ident => $outer_spawn:ident,\n     $inner_scope:ident => $inner_spawn:ident) => {{\n        let builder = ThreadPoolBuilder::new().num_threads(1);\n        let pool = builder.build().unwrap();\n        pool.install(|| {\n            let vec = Mutex::new(vec![]);\n            $outer_scope(|outer_scope| {\n                let vec = &vec;\n                spawn_push!(outer_scope.$outer_spawn, vec, 0);\n                $inner_scope(|inner_scope| {\n                    spawn_push!(inner_scope.$inner_spawn, vec, -1);\n                    spawn_push!(outer_scope.$outer_spawn, vec, 1);\n                    spawn_push!(inner_scope.$inner_spawn, vec, -2);\n                    spawn_push!(outer_scope.$outer_spawn, vec, 2);\n                    spawn_push!(inner_scope.$inner_spawn, vec, -3);\n                });\n                spawn_push!(outer_scope.$outer_spawn, vec, 3);\n            });\n            vec.into_inner().unwrap()\n        })\n    }};\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn mixed_lifo_order() {\n    // NB: the end of the inner scope makes us execute some of the outer scope\n    // before they've all been spawned, so they're not perfectly LIFO.\n    let vec = test_mixed_order!(scope => spawn, scope => spawn);\n    let expected = vec![-3, 2, -2, 1, -1, 3, 0];\n    assert_eq!(vec, expected);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn mixed_fifo_order() {\n    let vec = test_mixed_order!(scope_fifo => spawn_fifo, scope_fifo => spawn_fifo);\n    let expected = vec![-1, 0, -2, 1, -3, 2, 3];\n    assert_eq!(vec, expected);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn mixed_lifo_fifo_order() {\n    // NB: the end of the inner scope makes us execute some of the outer scope\n    // before they've all been spawned, so they're not perfectly LIFO.\n    let vec = test_mixed_order!(scope => spawn, scope_fifo => spawn_fifo);\n    let expected = vec![-1, 2, -2, 1, -3, 3, 0];\n    assert_eq!(vec, expected);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn mixed_fifo_lifo_order() {\n    let vec = test_mixed_order!(scope_fifo => spawn_fifo, scope => spawn);\n    let expected = vec![-3, 0, -2, 1, -1, 2, 3];\n    assert_eq!(vec, expected);\n}\n\n#[test]\nfn static_scope() {\n    static COUNTER: AtomicUsize = AtomicUsize::new(0);\n\n    let mut range = 0..100;\n    let sum = range.clone().sum();\n    let iter = &mut range;\n\n    COUNTER.store(0, Ordering::Relaxed);\n    scope(|s: &Scope<'static>| {\n        // While we're allowed the locally borrowed iterator,\n        // the spawns must be static.\n        for i in iter {\n            s.spawn(move |_| {\n                COUNTER.fetch_add(i, Ordering::Relaxed);\n            });\n        }\n    });\n\n    assert_eq!(COUNTER.load(Ordering::Relaxed), sum);\n}\n\n#[test]\nfn static_scope_fifo() {\n    static COUNTER: AtomicUsize = AtomicUsize::new(0);\n\n    let mut range = 0..100;\n    let sum = range.clone().sum();\n    let iter = &mut range;\n\n    COUNTER.store(0, Ordering::Relaxed);\n    scope_fifo(|s: &ScopeFifo<'static>| {\n        // While we're allowed the locally borrowed iterator,\n        // the spawns must be static.\n        for i in iter {\n            s.spawn_fifo(move |_| {\n                COUNTER.fetch_add(i, Ordering::Relaxed);\n            });\n        }\n    });\n\n    assert_eq!(COUNTER.load(Ordering::Relaxed), sum);\n}\n\n#[test]\nfn mixed_lifetime_scope() {\n    fn increment<'slice, 'counter>(counters: &'slice [&'counter AtomicUsize]) {\n        scope(move |s: &Scope<'counter>| {\n            // We can borrow 'slice here, but the spawns can only borrow 'counter.\n            for &c in counters {\n                s.spawn(move |_| {\n                    c.fetch_add(1, Ordering::Relaxed);\n                });\n            }\n        });\n    }\n\n    let counter = AtomicUsize::new(0);\n    increment(&[&counter; 100]);\n    assert_eq!(counter.into_inner(), 100);\n}\n\n#[test]\nfn mixed_lifetime_scope_fifo() {\n    fn increment<'slice, 'counter>(counters: &'slice [&'counter AtomicUsize]) {\n        scope_fifo(move |s: &ScopeFifo<'counter>| {\n            // We can borrow 'slice here, but the spawns can only borrow 'counter.\n            for &c in counters {\n                s.spawn_fifo(move |_| {\n                    c.fetch_add(1, Ordering::Relaxed);\n                });\n            }\n        });\n    }\n\n    let counter = AtomicUsize::new(0);\n    increment(&[&counter; 100]);\n    assert_eq!(counter.into_inner(), 100);\n}\n\n#[test]\nfn scope_spawn_broadcast() {\n    let sum = AtomicUsize::new(0);\n    let n = scope(|s| {\n        s.spawn_broadcast(|_, ctx| {\n            sum.fetch_add(ctx.index(), Ordering::Relaxed);\n        });\n        crate::current_num_threads()\n    });\n    assert_eq!(sum.into_inner(), n * (n - 1) / 2);\n}\n\n#[test]\nfn scope_fifo_spawn_broadcast() {\n    let sum = AtomicUsize::new(0);\n    let n = scope_fifo(|s| {\n        s.spawn_broadcast(|_, ctx| {\n            sum.fetch_add(ctx.index(), Ordering::Relaxed);\n        });\n        crate::current_num_threads()\n    });\n    assert_eq!(sum.into_inner(), n * (n - 1) / 2);\n}\n\n#[test]\nfn scope_spawn_broadcast_nested() {\n    let sum = AtomicUsize::new(0);\n    let n = scope(|s| {\n        s.spawn_broadcast(|s, _| {\n            s.spawn_broadcast(|_, ctx| {\n                sum.fetch_add(ctx.index(), Ordering::Relaxed);\n            });\n        });\n        crate::current_num_threads()\n    });\n    assert_eq!(sum.into_inner(), n * n * (n - 1) / 2);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn scope_spawn_broadcast_barrier() {\n    let barrier = Barrier::new(8);\n    let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap();\n    pool.in_place_scope(|s| {\n        s.spawn_broadcast(|_, _| {\n            barrier.wait();\n        });\n        barrier.wait();\n    });\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn scope_spawn_broadcast_panic_one() {\n    let count = AtomicUsize::new(0);\n    let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap();\n    let result = crate::unwind::halt_unwinding(|| {\n        pool.scope(|s| {\n            s.spawn_broadcast(|_, ctx| {\n                count.fetch_add(1, Ordering::Relaxed);\n                if ctx.index() == 3 {\n                    panic!(\"Hello, world!\");\n                }\n            });\n        });\n    });\n    assert_eq!(count.into_inner(), 7);\n    assert!(result.is_err(), \"broadcast panic should propagate!\");\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn scope_spawn_broadcast_panic_many() {\n    let count = AtomicUsize::new(0);\n    let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap();\n    let result = crate::unwind::halt_unwinding(|| {\n        pool.scope(|s| {\n            s.spawn_broadcast(|_, ctx| {\n                count.fetch_add(1, Ordering::Relaxed);\n                if ctx.index() % 2 == 0 {\n                    panic!(\"Hello, world!\");\n                }\n            });\n        });\n    });\n    assert_eq!(count.into_inner(), 7);\n    assert!(result.is_err(), \"broadcast panic should propagate!\");\n}\n"
  },
  {
    "path": "rayon-core/src/sleep/README.md",
    "content": "# Introduction: the sleep module\n\nThe code in this module governs when worker threads should go to\nsleep. The system used in this code was introduced in [Rayon RFC #5].\nThere is also a [video walkthrough] available. Both of those may be\nvaluable resources to understanding the code, though naturally they\nwill also grow stale over time. The comments in this file are\nextracted from the RFC and meant to be kept up to date.\n\n[Rayon RFC #5]: https://github.com/rayon-rs/rfcs/pull/5\n[video walkthrough]: https://youtu.be/HvmQsE5M4cY\n\n# The `Sleep` struct\n\nThe `Sleep` struct is embedded into each registry. It performs several functions:\n\n* It tracks when workers are awake or asleep.\n* It decides how long a worker should look for work before it goes to sleep,\n  via a callback that is invoked periodically from the worker's search loop.\n* It is notified when latches are set, jobs are published, or other\n  events occur, and it will go and wake the appropriate threads if\n  they are sleeping.\n\n# Thread states\n\nThere are three main thread states:\n\n* An **active** thread is one that is actively executing a job.\n* An **idle** thread is one that is searching for work to do. It will be\n  trying to steal work or pop work from the global injector queue.\n* A **sleeping** thread is one that is blocked on a condition variable,\n  waiting to be awoken.\n\nWe sometimes refer to the final two states collectively as **inactive**.\nThreads begin as idle but transition to idle and finally sleeping when\nthey're unable to find work to do.\n\n## Sleepy threads\n\nThere is one other special state worth mentioning. During the idle state,\nthreads can get **sleepy**. A sleepy thread is still idle, in that it is still\nsearching for work, but it is *about* to go to sleep after it does one more\nsearch (or some other number, potentially). When a thread enters the sleepy\nstate, it signals (via the **jobs event counter**, described below) that it is\nabout to go to sleep. If new work is published, this will lead to the counter\nbeing adjusted. When the thread actually goes to sleep, it will (hopefully, but\nnot guaranteed) see that the counter has changed and elect not to sleep, but\ninstead to search again. See the section on the **jobs event counter** for more\ndetails.\n\n# The counters\n\nOne of the key structs in the sleep module is `AtomicCounters`, found in\n`counters.rs`. It packs three counters into one atomically managed value:\n\n* Two **thread counters**, which track the number of threads in a particular state.\n* The **jobs event counter**, which is used to signal when new work is available.\n  It (sort of) tracks the number of jobs posted, but not quite, and it can rollover.\n\n## Thread counters\n\nThere are two thread counters, one that tracks **inactive** threads and one that\ntracks **sleeping** threads. From this, one can deduce the number of threads\nthat are idle by subtracting sleeping threads from inactive threads. We track\nthe counters in this way because it permits simpler atomic operations. One can\nincrement the number of sleeping threads (and thus decrease the number of idle\nthreads) simply by doing one atomic increment, for example. Similarly, one can\ndecrease the number of sleeping threads (and increase the number of idle\nthreads) through one atomic decrement.\n\nThese counters are adjusted as follows:\n\n* When a thread enters the idle state: increment the inactive thread counter.\n* When a thread enters the sleeping state: increment the sleeping thread counter.\n* When a thread awakens a sleeping thread: decrement the sleeping thread counter.\n  * Subtle point: the thread that *awakens* the sleeping thread decrements the\n    counter, not the thread that is *sleeping*. This is because there is a delay\n    between signaling a thread to wake and the thread actually waking:\n    decrementing the counter when awakening the thread means that other threads\n    that may be posting work will see the up-to-date value that much faster.\n* When a thread finds work, exiting the idle state: decrement the inactive\n  thread counter.\n\n## Jobs event counter\n\nThe final counter is the **jobs event counter**. The role of this counter is to\nhelp sleepy threads detect when new work is posted in a lightweight fashion. In\nits simplest form, we would simply have a counter that gets incremented each\ntime a new job is posted. This way, when a thread gets sleepy, it could read the\ncounter, and then compare to see if the value has changed before it actually\ngoes to sleep. But this [turns out to be too expensive] in practice, so we use a\nsomewhat more complex scheme.\n\n[turns out to be too expensive]: https://github.com/rayon-rs/rayon/pull/746#issuecomment-624802747\n\nThe idea is that the counter toggles between two states, depending on whether\nits value is even or odd (or, equivalently, on the value of its low bit):\n\n* Even -- If the low bit is zero, then it means that there has been no new work\n  since the last thread got sleepy.\n* Odd -- If the low bit is one, then it means that new work was posted since\n  the last thread got sleepy.\n\n### New work is posted\n\nWhen new work is posted, we check the value of the counter: if it is even,\nthen we increment it by one, so that it becomes odd.\n\n### Worker thread gets sleepy\n\nWhen a worker thread gets sleepy, it will read the value of the counter. If the\ncounter is odd, it will increment the counter so that it is even. Either way, it\nremembers the final value of the counter. The final value will be used later,\nwhen the thread is going to sleep. If at that time the counter has not changed,\nthen we can assume no new jobs have been posted (though note the remote\npossibility of rollover, discussed in detail below).\n\n# Protocol for a worker thread to post work\n\nThe full protocol for a thread to post work is as follows\n\n* If the work is posted into the injection queue, then execute a seq-cst fence (see below).\n* Load the counters, incrementing the JEC if it is even so that it is odd.\n* Check if there are idle threads available to handle this new job. If not,\n  and there are sleeping threads, then wake one or more threads.\n\n# Protocol for a worker thread to fall asleep\n\nThe full protocol for a thread to fall asleep is as follows:\n\n* After completing all its jobs, the worker goes idle and begins to\n  search for work. As it searches, it counts \"rounds\". In each round,\n  it searches all other work threads' queues, plus the 'injector queue' for\n  work injected from the outside. If work is found in this search, the thread\n  becomes active again and hence restarts this protocol from the top.\n* After a certain number of rounds, the thread \"gets sleepy\" and executes `get_sleepy`\n  above, remembering the `final_value` of the JEC. It does one more search for work.\n* If no work is found, the thread atomically:\n  * Checks the JEC to see that it has not changed from `final_value`.\n    * If it has, then the thread goes back to searching for work. We reset to\n      just before we got sleepy, so that we will do one more search\n      before attempting to sleep again (rather than searching for many rounds).\n  * Increments the number of sleeping threads by 1.\n* The thread then executes a seq-cst fence operation (see below).\n* The thread then does one final check for injected jobs (see below). If any\n  are available, it returns to the 'pre-sleepy' state as if the JEC had changed.\n* The thread waits to be signaled. Once signaled, it returns to the idle state.\n\n# The jobs event counter and deadlock\n\nAs described in the section on the JEC, the main concern around going to sleep\nis avoiding a race condition wherein:\n\n* Thread A looks for work, finds none.\n* Thread B posts work but sees no sleeping threads.\n* Thread A goes to sleep.\n\nThe JEC protocol largely prevents this, but due to rollover, this prevention is\nnot complete. It is possible -- if unlikely -- that enough activity occurs for\nThread A to observe the same JEC value that it saw when getting sleepy. If the\nnew work being published came from *inside* the thread pool, then this race\ncondition isn't too harmful. It means that we have fewer workers processing the\nwork then we should, but we won't deadlock. This seems like an acceptable risk\ngiven that this is unlikely in practice.\n\nHowever, if the work was posted as an *external* job, that is a problem. In that\ncase, it's possible that all of our workers could go to sleep, and the external\njob would never get processed. To prevent that, the sleeping protocol includes\none final check to see if the injector queue is empty before fully falling\nasleep. Note that this final check occurs **after** the number of sleeping\nthreads has been incremented. We are not concerned therefore with races against\ninjections that occur after that increment, only before.\n\nUnfortunately, there is one rather subtle point concerning this final check:\nwe wish to avoid the possibility that:\n\n* work is pushed into the injection queue by an outside thread X,\n* the sleepy thread S sees the JEC but it has rolled over and is equal\n* the sleepy thread S reads the injection queue but does not see the work posted by X.\n\nThis is possible because the C++ memory model typically offers guarantees of the\nform \"if you see the access A, then you must see those other accesses\" -- but it\ndoesn't guarantee that you will see the access A (i.e., if you think of\nprocessors with independent caches, you may be operating on very out of date\ncache state). \n\n## Using seq-cst fences to prevent deadlock\n\nTo overcome this problem, we have inserted two sequentially consistent fence\noperations into the protocols above:\n\n* One fence occurs after work is posted into the injection queue, but before the\n  counters are read (including the number of sleeping threads).\n  * Note that no fence is needed for work posted to internal queues, since it is ok\n    to overlook work in that case.\n* One fence occurs after the number of sleeping threads is incremented, but\n  before the injection queue is read.\n\n### Proof sketch\n\nWhat follows is a \"proof sketch\" that the protocol is deadlock free. We model\ntwo relevant bits of memory, the job injector queue J and the atomic counters C.\n\nConsider the actions of the injecting thread:\n\n* PushJob: Job is injected, which can be modeled as an atomic write to J with release semantics.\n* PushFence: A sequentially consistent fence is executed.\n* ReadSleepers: The counters C are read (they may also be incremented, but we just consider the read that comes first).\n\nMeanwhile, the sleepy thread does the following:\n\n* IncSleepers: The number of sleeping threads is incremented, which is atomic exchange to C.\n* SleepFence: A sequentially consistent fence is executed.\n* ReadJob: We look to see if the queue is empty, which is a read of J with acquire semantics.\n\nEither PushFence or SleepFence must come first:\n\n* If PushFence comes first, then PushJob must be visible to ReadJob.\n* If SleepFence comes first, then IncSleepers is visible to ReadSleepers.\n"
  },
  {
    "path": "rayon-core/src/sleep/counters.rs",
    "content": "use std::sync::atomic::{AtomicUsize, Ordering};\n\npub(super) struct AtomicCounters {\n    /// Packs together a number of counters. The counters are ordered as\n    /// follows, from least to most significant bits (here, we assuming\n    /// that [`THREADS_BITS`] is equal to 10):\n    ///\n    /// * Bits 0..10: Stores the number of **sleeping threads**\n    /// * Bits 10..20: Stores the number of **inactive threads**\n    /// * Bits 20..: Stores the **job event counter** (JEC)\n    ///\n    /// This uses 10 bits ([`THREADS_BITS`]) to encode the number of threads. Note\n    /// that the total number of bits (and hence the number of bits used for the\n    /// JEC) will depend on whether we are using a 32- or 64-bit architecture.\n    value: AtomicUsize,\n}\n\n#[derive(Copy, Clone)]\npub(super) struct Counters {\n    word: usize,\n}\n\n/// A value read from the **Jobs Event Counter**.\n/// See the [`README.md`](README.md) for more\n/// coverage of how the jobs event counter works.\n#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]\npub(super) struct JobsEventCounter(usize);\n\nimpl JobsEventCounter {\n    pub(super) const DUMMY: JobsEventCounter = JobsEventCounter(usize::MAX);\n\n    #[inline]\n    pub(super) fn as_usize(self) -> usize {\n        self.0\n    }\n\n    /// The JEC \"is sleepy\" if the last thread to increment it was in the\n    /// process of becoming sleepy. This is indicated by its value being *even*.\n    /// When new jobs are posted, they check if the JEC is sleepy, and if so\n    /// they incremented it.\n    #[inline]\n    pub(super) fn is_sleepy(self) -> bool {\n        (self.as_usize() & 1) == 0\n    }\n\n    /// The JEC \"is active\" if the last thread to increment it was posting new\n    /// work. This is indicated by its value being *odd*. When threads get\n    /// sleepy, they will check if the JEC is active, and increment it.\n    #[inline]\n    pub(super) fn is_active(self) -> bool {\n        !self.is_sleepy()\n    }\n}\n\n/// Number of bits used for the thread counters.\n#[cfg(target_pointer_width = \"64\")]\nconst THREADS_BITS: usize = 16;\n\n#[cfg(target_pointer_width = \"32\")]\nconst THREADS_BITS: usize = 8;\n\n/// Bits to shift to select the sleeping threads\n/// (used with `select_bits`).\n#[allow(clippy::erasing_op)]\nconst SLEEPING_SHIFT: usize = 0 * THREADS_BITS;\n\n/// Bits to shift to select the inactive threads\n/// (used with `select_bits`).\n#[allow(clippy::identity_op)]\nconst INACTIVE_SHIFT: usize = 1 * THREADS_BITS;\n\n/// Bits to shift to select the JEC\n/// (use JOBS_BITS).\nconst JEC_SHIFT: usize = 2 * THREADS_BITS;\n\n/// Max value for the thread counters.\npub(crate) const THREADS_MAX: usize = (1 << THREADS_BITS) - 1;\n\n/// Constant that can be added to add one sleeping thread.\nconst ONE_SLEEPING: usize = 1;\n\n/// Constant that can be added to add one inactive thread.\n/// An inactive thread is either idle, sleepy, or sleeping.\nconst ONE_INACTIVE: usize = 1 << INACTIVE_SHIFT;\n\n/// Constant that can be added to add one to the JEC.\nconst ONE_JEC: usize = 1 << JEC_SHIFT;\n\nimpl AtomicCounters {\n    #[inline]\n    pub(super) fn new() -> AtomicCounters {\n        AtomicCounters {\n            value: AtomicUsize::new(0),\n        }\n    }\n\n    /// Load and return the current value of the various counters.\n    /// This value can then be given to other method which will\n    /// attempt to update the counters via compare-and-swap.\n    #[inline]\n    pub(super) fn load(&self, ordering: Ordering) -> Counters {\n        Counters::new(self.value.load(ordering))\n    }\n\n    #[inline]\n    fn try_exchange(&self, old_value: Counters, new_value: Counters, ordering: Ordering) -> bool {\n        self.value\n            .compare_exchange(old_value.word, new_value.word, ordering, Ordering::Relaxed)\n            .is_ok()\n    }\n\n    /// Adds an inactive thread. This cannot fail.\n    ///\n    /// This should be invoked when a thread enters its idle loop looking\n    /// for work. It is decremented when work is found. Note that it is\n    /// not decremented if the thread transitions from idle to sleepy or sleeping;\n    /// so the number of inactive threads is always greater-than-or-equal\n    /// to the number of sleeping threads.\n    #[inline]\n    pub(super) fn add_inactive_thread(&self) {\n        self.value.fetch_add(ONE_INACTIVE, Ordering::SeqCst);\n    }\n\n    /// Increments the jobs event counter if `increment_when`, when applied to\n    /// the current value, is true. Used to toggle the JEC from even (sleepy) to\n    /// odd (active) or vice versa. Returns the final value of the counters, for\n    /// which `increment_when` is guaranteed to return false.\n    pub(super) fn increment_jobs_event_counter_if(\n        &self,\n        increment_when: impl Fn(JobsEventCounter) -> bool,\n    ) -> Counters {\n        loop {\n            let old_value = self.load(Ordering::SeqCst);\n            if increment_when(old_value.jobs_counter()) {\n                let new_value = old_value.increment_jobs_counter();\n                if self.try_exchange(old_value, new_value, Ordering::SeqCst) {\n                    return new_value;\n                }\n            } else {\n                return old_value;\n            }\n        }\n    }\n\n    /// Subtracts an inactive thread. This cannot fail. It is invoked\n    /// when a thread finds work and hence becomes active. It returns the\n    /// number of sleeping threads to wake up (if any).\n    ///\n    /// See `add_inactive_thread`.\n    #[inline]\n    pub(super) fn sub_inactive_thread(&self) -> usize {\n        let old_value = Counters::new(self.value.fetch_sub(ONE_INACTIVE, Ordering::SeqCst));\n        debug_assert!(\n            old_value.inactive_threads() > 0,\n            \"sub_inactive_thread: old_value {old_value:?} has no inactive threads\",\n        );\n        debug_assert!(\n            old_value.sleeping_threads() <= old_value.inactive_threads(),\n            \"sub_inactive_thread: old_value {:?} had {} sleeping threads and {} inactive threads\",\n            old_value,\n            old_value.sleeping_threads(),\n            old_value.inactive_threads(),\n        );\n\n        // Current heuristic: whenever an inactive thread goes away, if\n        // there are any sleeping threads, wake 'em up.\n        let sleeping_threads = old_value.sleeping_threads();\n        Ord::min(sleeping_threads, 2)\n    }\n\n    /// Subtracts a sleeping thread. This cannot fail, but it is only\n    /// safe to do if you you know the number of sleeping threads is\n    /// non-zero (i.e., because you have just awoken a sleeping\n    /// thread).\n    #[inline]\n    pub(super) fn sub_sleeping_thread(&self) {\n        let old_value = Counters::new(self.value.fetch_sub(ONE_SLEEPING, Ordering::SeqCst));\n        debug_assert!(\n            old_value.sleeping_threads() > 0,\n            \"sub_sleeping_thread: old_value {old_value:?} had no sleeping threads\",\n        );\n        debug_assert!(\n            old_value.sleeping_threads() <= old_value.inactive_threads(),\n            \"sub_sleeping_thread: old_value {:?} had {} sleeping threads and {} inactive threads\",\n            old_value,\n            old_value.sleeping_threads(),\n            old_value.inactive_threads(),\n        );\n    }\n\n    #[inline]\n    pub(super) fn try_add_sleeping_thread(&self, old_value: Counters) -> bool {\n        debug_assert!(\n            old_value.inactive_threads() > 0,\n            \"try_add_sleeping_thread: old_value {old_value:?} has no inactive threads\",\n        );\n        debug_assert!(\n            old_value.sleeping_threads() < THREADS_MAX,\n            \"try_add_sleeping_thread: old_value {old_value:?} has too many sleeping threads\",\n        );\n\n        let mut new_value = old_value;\n        new_value.word += ONE_SLEEPING;\n\n        self.try_exchange(old_value, new_value, Ordering::SeqCst)\n    }\n}\n\n#[inline]\nfn select_thread(word: usize, shift: usize) -> usize {\n    (word >> shift) & THREADS_MAX\n}\n\n#[inline]\nfn select_jec(word: usize) -> usize {\n    word >> JEC_SHIFT\n}\n\nimpl Counters {\n    #[inline]\n    fn new(word: usize) -> Counters {\n        Counters { word }\n    }\n\n    #[inline]\n    fn increment_jobs_counter(self) -> Counters {\n        // We can freely add to JEC because it occupies the most significant bits.\n        // Thus it doesn't overflow into the other counters, just wraps itself.\n        Counters {\n            word: self.word.wrapping_add(ONE_JEC),\n        }\n    }\n\n    #[inline]\n    pub(super) fn jobs_counter(self) -> JobsEventCounter {\n        JobsEventCounter(select_jec(self.word))\n    }\n\n    /// The number of threads that are not actively\n    /// executing work. They may be idle, sleepy, or asleep.\n    #[inline]\n    pub(super) fn inactive_threads(self) -> usize {\n        select_thread(self.word, INACTIVE_SHIFT)\n    }\n\n    #[inline]\n    pub(super) fn awake_but_idle_threads(self) -> usize {\n        debug_assert!(\n            self.sleeping_threads() <= self.inactive_threads(),\n            \"sleeping threads: {} > raw idle threads {}\",\n            self.sleeping_threads(),\n            self.inactive_threads()\n        );\n        self.inactive_threads() - self.sleeping_threads()\n    }\n\n    #[inline]\n    pub(super) fn sleeping_threads(self) -> usize {\n        select_thread(self.word, SLEEPING_SHIFT)\n    }\n}\n\nimpl std::fmt::Debug for Counters {\n    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        let word = format!(\"{:016x}\", self.word);\n        fmt.debug_struct(\"Counters\")\n            .field(\"word\", &word)\n            .field(\"jobs\", &self.jobs_counter().0)\n            .field(\"inactive\", &self.inactive_threads())\n            .field(\"sleeping\", &self.sleeping_threads())\n            .finish()\n    }\n}\n"
  },
  {
    "path": "rayon-core/src/sleep/mod.rs",
    "content": "//! Code that decides when workers should go to sleep. See README.md\n//! for an overview.\n\nuse crate::latch::CoreLatch;\nuse crate::sync::{Condvar, Mutex};\nuse crossbeam_utils::CachePadded;\nuse std::sync::atomic::Ordering;\nuse std::thread;\n\nmod counters;\npub(crate) use self::counters::THREADS_MAX;\nuse self::counters::{AtomicCounters, JobsEventCounter};\n\n/// The `Sleep` struct is embedded into each registry. It governs the waking and sleeping\n/// of workers. It has callbacks that are invoked periodically at significant events,\n/// such as when workers are looping and looking for work, when latches are set, or when\n/// jobs are published, and it either blocks threads or wakes them in response to these\n/// events. See the [`README.md`] in this module for more details.\n///\n/// [`README.md`] README.md\npub(super) struct Sleep {\n    /// One \"sleep state\" per worker. Used to track if a worker is sleeping and to have\n    /// them block.\n    worker_sleep_states: Vec<CachePadded<WorkerSleepState>>,\n\n    counters: AtomicCounters,\n}\n\n/// An instance of this struct is created when a thread becomes idle.\n/// It is consumed when the thread finds work, and passed by `&mut`\n/// reference for operations that preserve the idle state. (In other\n/// words, producing one of these structs is evidence the thread is\n/// idle.) It tracks state such as how long the thread has been idle.\npub(super) struct IdleState {\n    /// What is worker index of the idle thread?\n    worker_index: usize,\n\n    /// How many rounds have we been circling without sleeping?\n    rounds: u32,\n\n    /// Once we become sleepy, what was the sleepy counter value?\n    /// Set to `INVALID_SLEEPY_COUNTER` otherwise.\n    jobs_counter: JobsEventCounter,\n}\n\n/// The \"sleep state\" for an individual worker.\n#[derive(Default)]\nstruct WorkerSleepState {\n    /// Set to true when the worker goes to sleep; set to false when\n    /// the worker is notified or when it wakes.\n    is_blocked: Mutex<bool>,\n\n    condvar: Condvar,\n}\n\nconst ROUNDS_UNTIL_SLEEPY: u32 = 32;\nconst ROUNDS_UNTIL_SLEEPING: u32 = ROUNDS_UNTIL_SLEEPY + 1;\n\nimpl Sleep {\n    pub(super) fn new(n_threads: usize) -> Sleep {\n        assert!(n_threads <= THREADS_MAX);\n        Sleep {\n            worker_sleep_states: (0..n_threads).map(|_| Default::default()).collect(),\n            counters: AtomicCounters::new(),\n        }\n    }\n\n    #[inline]\n    pub(super) fn start_looking(&self, worker_index: usize) -> IdleState {\n        self.counters.add_inactive_thread();\n\n        IdleState {\n            worker_index,\n            rounds: 0,\n            jobs_counter: JobsEventCounter::DUMMY,\n        }\n    }\n\n    #[inline]\n    pub(super) fn work_found(&self) {\n        // If we were the last idle thread and other threads are still sleeping,\n        // then we should wake up another thread.\n        let threads_to_wake = self.counters.sub_inactive_thread();\n        self.wake_any_threads(threads_to_wake as u32);\n    }\n\n    #[inline]\n    pub(super) fn no_work_found(\n        &self,\n        idle_state: &mut IdleState,\n        latch: &CoreLatch,\n        has_injected_jobs: impl FnOnce() -> bool,\n    ) {\n        if idle_state.rounds < ROUNDS_UNTIL_SLEEPY {\n            thread::yield_now();\n            idle_state.rounds += 1;\n        } else if idle_state.rounds == ROUNDS_UNTIL_SLEEPY {\n            idle_state.jobs_counter = self.announce_sleepy();\n            idle_state.rounds += 1;\n            thread::yield_now();\n        } else if idle_state.rounds < ROUNDS_UNTIL_SLEEPING {\n            idle_state.rounds += 1;\n            thread::yield_now();\n        } else {\n            debug_assert_eq!(idle_state.rounds, ROUNDS_UNTIL_SLEEPING);\n            self.sleep(idle_state, latch, has_injected_jobs);\n        }\n    }\n\n    #[cold]\n    fn announce_sleepy(&self) -> JobsEventCounter {\n        self.counters\n            .increment_jobs_event_counter_if(JobsEventCounter::is_active)\n            .jobs_counter()\n    }\n\n    #[cold]\n    fn sleep(\n        &self,\n        idle_state: &mut IdleState,\n        latch: &CoreLatch,\n        has_injected_jobs: impl FnOnce() -> bool,\n    ) {\n        let worker_index = idle_state.worker_index;\n\n        if !latch.get_sleepy() {\n            return;\n        }\n\n        let sleep_state = &self.worker_sleep_states[worker_index];\n        let mut is_blocked = sleep_state.is_blocked.lock().unwrap();\n        debug_assert!(!*is_blocked);\n\n        // Our latch was signalled. We should wake back up fully as we\n        // will have some stuff to do.\n        if !latch.fall_asleep() {\n            idle_state.wake_fully();\n            return;\n        }\n\n        loop {\n            let counters = self.counters.load(Ordering::SeqCst);\n\n            // Check if the JEC has changed since we got sleepy.\n            debug_assert!(idle_state.jobs_counter.is_sleepy());\n            if counters.jobs_counter() != idle_state.jobs_counter {\n                // JEC has changed, so a new job was posted, but for some reason\n                // we didn't see it. We should return to just before the SLEEPY\n                // state so we can do another search and (if we fail to find\n                // work) go back to sleep.\n                idle_state.wake_partly();\n                latch.wake_up();\n                return;\n            }\n\n            // Otherwise, let's move from IDLE to SLEEPING.\n            if self.counters.try_add_sleeping_thread(counters) {\n                break;\n            }\n        }\n\n        // Successfully registered as asleep.\n\n        // We have one last check for injected jobs to do. This protects against\n        // deadlock in the very unlikely event that\n        //\n        // - an external job is being injected while we are sleepy\n        // - that job triggers the rollover over the JEC such that we don't see it\n        // - we are the last active worker thread\n        std::sync::atomic::fence(Ordering::SeqCst);\n        if has_injected_jobs() {\n            // If we see an externally injected job, then we have to 'wake\n            // ourselves up'. (Ordinarily, `sub_sleeping_thread` is invoked by\n            // the one that wakes us.)\n            self.counters.sub_sleeping_thread();\n        } else {\n            // If we don't see an injected job (the normal case), then flag\n            // ourselves as asleep and wait till we are notified.\n            //\n            // (Note that `is_blocked` is held under a mutex and the mutex was\n            // acquired *before* we incremented the \"sleepy counter\". This means\n            // that whomever is coming to wake us will have to wait until we\n            // release the mutex in the call to `wait`, so they will see this\n            // boolean as true.)\n            *is_blocked = true;\n            while *is_blocked {\n                is_blocked = sleep_state.condvar.wait(is_blocked).unwrap();\n            }\n        }\n\n        // Update other state:\n        idle_state.wake_fully();\n        latch.wake_up();\n    }\n\n    /// Notify the given thread that it should wake up (if it is\n    /// sleeping).  When this method is invoked, we typically know the\n    /// thread is asleep, though in rare cases it could have been\n    /// awoken by (e.g.) new work having been posted.\n    pub(super) fn notify_worker_latch_is_set(&self, target_worker_index: usize) {\n        self.wake_specific_thread(target_worker_index);\n    }\n\n    /// Signals that `num_jobs` new jobs were injected into the thread\n    /// pool from outside. This function will ensure that there are\n    /// threads available to process them, waking threads from sleep\n    /// if necessary.\n    ///\n    /// # Parameters\n    ///\n    /// - `num_jobs` -- lower bound on number of jobs available for stealing.\n    ///   We'll try to get at least one thread per job.\n    #[inline]\n    pub(super) fn new_injected_jobs(&self, num_jobs: u32, queue_was_empty: bool) {\n        // This fence is needed to guarantee that threads\n        // as they are about to fall asleep, observe any\n        // new jobs that may have been injected.\n        std::sync::atomic::fence(Ordering::SeqCst);\n\n        self.new_jobs(num_jobs, queue_was_empty)\n    }\n\n    /// Signals that `num_jobs` new jobs were pushed onto a thread's\n    /// local deque. This function will try to ensure that there are\n    /// threads available to process them, waking threads from sleep\n    /// if necessary. However, this is not guaranteed: under certain\n    /// race conditions, the function may fail to wake any new\n    /// threads; in that case the existing thread should eventually\n    /// pop the job.\n    ///\n    /// # Parameters\n    ///\n    /// - `num_jobs` -- lower bound on number of jobs available for stealing.\n    ///   We'll try to get at least one thread per job.\n    #[inline]\n    pub(super) fn new_internal_jobs(&self, num_jobs: u32, queue_was_empty: bool) {\n        self.new_jobs(num_jobs, queue_was_empty)\n    }\n\n    /// Common helper for `new_injected_jobs` and `new_internal_jobs`.\n    #[inline]\n    fn new_jobs(&self, num_jobs: u32, queue_was_empty: bool) {\n        // Read the counters and -- if sleepy workers have announced themselves\n        // -- announce that there is now work available. The final value of `counters`\n        // with which we exit the loop thus corresponds to a state when\n        let counters = self\n            .counters\n            .increment_jobs_event_counter_if(JobsEventCounter::is_sleepy);\n        let num_awake_but_idle = counters.awake_but_idle_threads();\n        let num_sleepers = counters.sleeping_threads();\n\n        if num_sleepers == 0 {\n            // nobody to wake\n            return;\n        }\n\n        // Promote from u16 to u32 so we can interoperate with\n        // num_jobs more easily.\n        let num_awake_but_idle = num_awake_but_idle as u32;\n        let num_sleepers = num_sleepers as u32;\n\n        // If the queue is non-empty, then we always wake up a worker\n        // -- clearly the existing idle jobs aren't enough. Otherwise,\n        // check to see if we have enough idle workers.\n        if !queue_was_empty {\n            let num_to_wake = Ord::min(num_jobs, num_sleepers);\n            self.wake_any_threads(num_to_wake);\n        } else if num_awake_but_idle < num_jobs {\n            let num_to_wake = Ord::min(num_jobs - num_awake_but_idle, num_sleepers);\n            self.wake_any_threads(num_to_wake);\n        }\n    }\n\n    #[cold]\n    fn wake_any_threads(&self, mut num_to_wake: u32) {\n        if num_to_wake > 0 {\n            for i in 0..self.worker_sleep_states.len() {\n                if self.wake_specific_thread(i) {\n                    num_to_wake -= 1;\n                    if num_to_wake == 0 {\n                        return;\n                    }\n                }\n            }\n        }\n    }\n\n    fn wake_specific_thread(&self, index: usize) -> bool {\n        let sleep_state = &self.worker_sleep_states[index];\n\n        let mut is_blocked = sleep_state.is_blocked.lock().unwrap();\n        if *is_blocked {\n            *is_blocked = false;\n            sleep_state.condvar.notify_one();\n\n            // When the thread went to sleep, it will have incremented\n            // this value. When we wake it, its our job to decrement\n            // it. We could have the thread do it, but that would\n            // introduce a delay between when the thread was\n            // *notified* and when this counter was decremented. That\n            // might mislead people with new work into thinking that\n            // there are sleeping threads that they should try to\n            // wake, when in fact there is nothing left for them to\n            // do.\n            self.counters.sub_sleeping_thread();\n\n            true\n        } else {\n            false\n        }\n    }\n}\n\nimpl IdleState {\n    fn wake_fully(&mut self) {\n        self.rounds = 0;\n        self.jobs_counter = JobsEventCounter::DUMMY;\n    }\n\n    fn wake_partly(&mut self) {\n        self.rounds = ROUNDS_UNTIL_SLEEPY;\n        self.jobs_counter = JobsEventCounter::DUMMY;\n    }\n}\n"
  },
  {
    "path": "rayon-core/src/spawn/mod.rs",
    "content": "use crate::job::*;\nuse crate::registry::Registry;\nuse crate::unwind;\nuse std::mem;\nuse std::sync::Arc;\n\n/// Puts the task into the Rayon thread pool's job queue in the \"static\"\n/// or \"global\" scope. Just like a standard thread, this task is not\n/// tied to the current stack frame, and hence it cannot hold any\n/// references other than those with `'static` lifetime. If you want\n/// to spawn a task that references stack data, use [the `scope()`\n/// function] to create a scope.\n///\n/// [the `scope()` function]: crate::scope()\n///\n/// Since tasks spawned with this function cannot hold references into\n/// the enclosing stack frame, you almost certainly want to use a\n/// `move` closure as their argument (otherwise, the closure will\n/// typically hold references to any variables from the enclosing\n/// function that you happen to use).\n///\n/// This API assumes that the closure is executed purely for its\n/// side-effects (i.e., it might send messages, modify data protected\n/// by a mutex, or some such thing).\n///\n/// There is no guaranteed order of execution for spawns, given that\n/// other threads may steal tasks at any time. However, they are\n/// generally prioritized in a LIFO order on the thread from which\n/// they were spawned. Other threads always steal from the other end of\n/// the deque, like FIFO order.  The idea is that \"recent\" tasks are\n/// most likely to be fresh in the local CPU's cache, while other\n/// threads can steal older \"stale\" tasks.  For an alternate approach,\n/// consider [`spawn_fifo()`] instead.\n///\n/// # Panic handling\n///\n/// If this closure should panic, the resulting panic will be\n/// propagated to the panic handler registered in the `ThreadPoolBuilder`,\n/// if any.  See [`ThreadPoolBuilder::panic_handler()`] for more\n/// details.\n///\n/// [`ThreadPoolBuilder::panic_handler()`]: crate::ThreadPoolBuilder::panic_handler()\n///\n/// # Examples\n///\n/// This code creates a Rayon task that increments a global counter.\n///\n/// ```rust\n/// # use rayon_core as rayon;\n/// use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};\n///\n/// static GLOBAL_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;\n///\n/// rayon::spawn(move || {\n///     GLOBAL_COUNTER.fetch_add(1, Ordering::SeqCst);\n/// });\n/// ```\npub fn spawn<F>(func: F)\nwhere\n    F: FnOnce() + Send + 'static,\n{\n    // We assert that current registry has not terminated.\n    unsafe { spawn_in(func, &Registry::current()) }\n}\n\n/// Spawns an asynchronous job in `registry.`\n///\n/// Unsafe because `registry` must not yet have terminated.\npub(super) unsafe fn spawn_in<F>(func: F, registry: &Arc<Registry>)\nwhere\n    F: FnOnce() + Send + 'static,\n{\n    // We assert that this does not hold any references (we know\n    // this because of the `'static` bound in the interface);\n    // moreover, we assert that the code below is not supposed to\n    // be able to panic, and hence the data won't leak but will be\n    // enqueued into some deque for later execution.\n    let abort_guard = unwind::AbortIfPanic; // just in case we are wrong, and code CAN panic\n    let job_ref = spawn_job(func, registry);\n    registry.inject_or_push(job_ref);\n    mem::forget(abort_guard);\n}\n\nunsafe fn spawn_job<F>(func: F, registry: &Arc<Registry>) -> JobRef\nwhere\n    F: FnOnce() + Send + 'static,\n{\n    // Ensure that registry cannot terminate until this job has\n    // executed. This ref is decremented at the (*) below.\n    registry.increment_terminate_count();\n\n    HeapJob::new({\n        let registry = Arc::clone(registry);\n        move || {\n            registry.catch_unwind(func);\n            registry.terminate(); // (*) permit registry to terminate now\n        }\n    })\n    .into_static_job_ref()\n}\n\n/// Fires off a task into the Rayon thread pool in the \"static\" or\n/// \"global\" scope.  Just like a standard thread, this task is not\n/// tied to the current stack frame, and hence it cannot hold any\n/// references other than those with `'static` lifetime. If you want\n/// to spawn a task that references stack data, use [the `scope_fifo()`\n/// function] to create a scope.\n///\n/// The behavior is essentially the same as [the `spawn`\n/// function], except that calls from the same thread\n/// will be prioritized in FIFO order. This is similar to the now-\n/// deprecated [`breadth_first`] option, except the effect is isolated\n/// to relative `spawn_fifo` calls, not all thread-pool tasks.\n///\n/// For more details on this design, see Rayon [RFC #1].\n///\n/// [the `scope_fifo()` function]: crate::scope_fifo()\n/// [the `spawn` function]: crate::spawn()\n/// [`breadth_first`]: crate::ThreadPoolBuilder::breadth_first\n/// [RFC #1]: https://github.com/rayon-rs/rfcs/blob/main/accepted/rfc0001-scope-scheduling.md\n///\n/// # Panic handling\n///\n/// If this closure should panic, the resulting panic will be\n/// propagated to the panic handler registered in the `ThreadPoolBuilder`,\n/// if any.  See [`ThreadPoolBuilder::panic_handler()`] for more\n/// details.\n///\n/// [`ThreadPoolBuilder::panic_handler()`]: crate::ThreadPoolBuilder::panic_handler\npub fn spawn_fifo<F>(func: F)\nwhere\n    F: FnOnce() + Send + 'static,\n{\n    // We assert that current registry has not terminated.\n    unsafe { spawn_fifo_in(func, &Registry::current()) }\n}\n\n/// Spawns an asynchronous FIFO job in `registry.`\n///\n/// Unsafe because `registry` must not yet have terminated.\npub(super) unsafe fn spawn_fifo_in<F>(func: F, registry: &Arc<Registry>)\nwhere\n    F: FnOnce() + Send + 'static,\n{\n    // We assert that this does not hold any references (we know\n    // this because of the `'static` bound in the interface);\n    // moreover, we assert that the code below is not supposed to\n    // be able to panic, and hence the data won't leak but will be\n    // enqueued into some deque for later execution.\n    let abort_guard = unwind::AbortIfPanic; // just in case we are wrong, and code CAN panic\n    let job_ref = spawn_job(func, registry);\n\n    // If we're in the pool, use our thread's private fifo for this thread to execute\n    // in a locally-FIFO order.  Otherwise, just use the pool's global injector.\n    match registry.current_thread() {\n        Some(worker) => worker.push_fifo(job_ref),\n        None => registry.inject(job_ref),\n    }\n    mem::forget(abort_guard);\n}\n\n#[cfg(test)]\nmod test;\n"
  },
  {
    "path": "rayon-core/src/spawn/test.rs",
    "content": "use crate::scope;\nuse std::any::Any;\nuse std::sync::mpsc::channel;\nuse std::sync::Mutex;\n\nuse super::{spawn, spawn_fifo};\nuse crate::ThreadPoolBuilder;\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn spawn_then_join_in_worker() {\n    let (tx, rx) = channel();\n    scope(move |_| {\n        spawn(move || tx.send(22).unwrap());\n    });\n    assert_eq!(22, rx.recv().unwrap());\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn spawn_then_join_outside_worker() {\n    let (tx, rx) = channel();\n    spawn(move || tx.send(22).unwrap());\n    assert_eq!(22, rx.recv().unwrap());\n}\n\n#[test]\n#[cfg_attr(not(panic = \"unwind\"), ignore)]\nfn panic_fwd() {\n    let (tx, rx) = channel();\n\n    let tx = Mutex::new(tx);\n    let panic_handler = move |err: Box<dyn Any + Send>| {\n        let tx = tx.lock().unwrap();\n        if let Some(&msg) = err.downcast_ref::<&str>() {\n            if msg == \"Hello, world!\" {\n                tx.send(1).unwrap();\n            } else {\n                tx.send(2).unwrap();\n            }\n        } else {\n            tx.send(3).unwrap();\n        }\n    };\n\n    let builder = ThreadPoolBuilder::new().panic_handler(panic_handler);\n\n    builder\n        .build()\n        .unwrap()\n        .spawn(move || panic!(\"Hello, world!\"));\n\n    assert_eq!(1, rx.recv().unwrap());\n}\n\n/// Test what happens when the thread pool is dropped but there are\n/// still active asynchronous tasks. We expect the thread pool to stay\n/// alive and executing until those threads are complete.\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn termination_while_things_are_executing() {\n    let (tx0, rx0) = channel();\n    let (tx1, rx1) = channel();\n\n    // Create a thread pool and spawn some code in it, but then drop\n    // our reference to it.\n    {\n        let thread_pool = ThreadPoolBuilder::new().build().unwrap();\n        thread_pool.spawn(move || {\n            let data = rx0.recv().unwrap();\n\n            // At this point, we know the \"main\" reference to the\n            // `ThreadPool` has been dropped, but there are still\n            // active threads. Launch one more.\n            spawn(move || {\n                tx1.send(data).unwrap();\n            });\n        });\n    }\n\n    tx0.send(22).unwrap();\n    let v = rx1.recv().unwrap();\n    assert_eq!(v, 22);\n}\n\n#[test]\n#[cfg_attr(not(panic = \"unwind\"), ignore)]\nfn custom_panic_handler_and_spawn() {\n    let (tx, rx) = channel();\n\n    // Create a parallel closure that will send panics on the\n    // channel; since the closure is potentially executed in parallel\n    // with itself, we have to wrap `tx` in a mutex.\n    let tx = Mutex::new(tx);\n    let panic_handler = move |e: Box<dyn Any + Send>| {\n        tx.lock().unwrap().send(e).unwrap();\n    };\n\n    // Execute an async that will panic.\n    let builder = ThreadPoolBuilder::new().panic_handler(panic_handler);\n    builder.build().unwrap().spawn(move || {\n        panic!(\"Hello, world!\");\n    });\n\n    // Check that we got back the panic we expected.\n    let error = rx.recv().unwrap();\n    if let Some(&msg) = error.downcast_ref::<&str>() {\n        assert_eq!(msg, \"Hello, world!\");\n    } else {\n        panic!(\"did not receive a string from panic handler\");\n    }\n}\n\n#[test]\n#[cfg_attr(not(panic = \"unwind\"), ignore)]\nfn custom_panic_handler_and_nested_spawn() {\n    let (tx, rx) = channel();\n\n    // Create a parallel closure that will send panics on the\n    // channel; since the closure is potentially executed in parallel\n    // with itself, we have to wrap `tx` in a mutex.\n    let tx = Mutex::new(tx);\n    let panic_handler = move |e| {\n        tx.lock().unwrap().send(e).unwrap();\n    };\n\n    // Execute an async that will (eventually) panic.\n    const PANICS: usize = 3;\n    let builder = ThreadPoolBuilder::new().panic_handler(panic_handler);\n    builder.build().unwrap().spawn(move || {\n        // launch 3 nested spawn-asyncs; these should be in the same\n        // thread pool and hence inherit the same panic handler\n        for _ in 0..PANICS {\n            spawn(move || {\n                panic!(\"Hello, world!\");\n            });\n        }\n    });\n\n    // Check that we get back the panics we expected.\n    for _ in 0..PANICS {\n        let error = rx.recv().unwrap();\n        if let Some(&msg) = error.downcast_ref::<&str>() {\n            assert_eq!(msg, \"Hello, world!\");\n        } else {\n            panic!(\"did not receive a string from panic handler\");\n        }\n    }\n}\n\nmacro_rules! test_order {\n    ($outer_spawn:ident, $inner_spawn:ident) => {{\n        let builder = ThreadPoolBuilder::new().num_threads(1);\n        let pool = builder.build().unwrap();\n        let (tx, rx) = channel();\n        pool.install(move || {\n            for i in 0..10 {\n                let tx = tx.clone();\n                $outer_spawn(move || {\n                    for j in 0..10 {\n                        let tx = tx.clone();\n                        $inner_spawn(move || {\n                            tx.send(i * 10 + j).unwrap();\n                        });\n                    }\n                });\n            }\n        });\n        rx.iter().collect::<Vec<i32>>()\n    }};\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn lifo_order() {\n    // In the absence of stealing, `spawn()` jobs on a thread will run in LIFO order.\n    let vec = test_order!(spawn, spawn);\n    let expected: Vec<i32> = (0..100).rev().collect(); // LIFO -> reversed\n    assert_eq!(vec, expected);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn fifo_order() {\n    // In the absence of stealing, `spawn_fifo()` jobs on a thread will run in FIFO order.\n    let vec = test_order!(spawn_fifo, spawn_fifo);\n    let expected: Vec<i32> = (0..100).collect(); // FIFO -> natural order\n    assert_eq!(vec, expected);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn lifo_fifo_order() {\n    // LIFO on the outside, FIFO on the inside\n    let vec = test_order!(spawn, spawn_fifo);\n    let expected: Vec<i32> = (0..10)\n        .rev()\n        .flat_map(|i| (0..10).map(move |j| i * 10 + j))\n        .collect();\n    assert_eq!(vec, expected);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn fifo_lifo_order() {\n    // FIFO on the outside, LIFO on the inside\n    let vec = test_order!(spawn_fifo, spawn);\n    let expected: Vec<i32> = (0..10)\n        .flat_map(|i| (0..10).rev().map(move |j| i * 10 + j))\n        .collect();\n    assert_eq!(vec, expected);\n}\n\nmacro_rules! spawn_send {\n    ($spawn:ident, $tx:ident, $i:expr) => {{\n        let tx = $tx.clone();\n        $spawn(move || tx.send($i).unwrap());\n    }};\n}\n\n/// Test mixed spawns pushing a series of numbers, interleaved such\n/// such that negative values are using the second kind of spawn.\nmacro_rules! test_mixed_order {\n    ($pos_spawn:ident, $neg_spawn:ident) => {{\n        let builder = ThreadPoolBuilder::new().num_threads(1);\n        let pool = builder.build().unwrap();\n        let (tx, rx) = channel();\n        pool.install(move || {\n            spawn_send!($pos_spawn, tx, 0);\n            spawn_send!($neg_spawn, tx, -1);\n            spawn_send!($pos_spawn, tx, 1);\n            spawn_send!($neg_spawn, tx, -2);\n            spawn_send!($pos_spawn, tx, 2);\n            spawn_send!($neg_spawn, tx, -3);\n            spawn_send!($pos_spawn, tx, 3);\n        });\n        rx.iter().collect::<Vec<i32>>()\n    }};\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn mixed_lifo_fifo_order() {\n    let vec = test_mixed_order!(spawn, spawn_fifo);\n    let expected = vec![3, -1, 2, -2, 1, -3, 0];\n    assert_eq!(vec, expected);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn mixed_fifo_lifo_order() {\n    let vec = test_mixed_order!(spawn_fifo, spawn);\n    let expected = vec![0, -3, 1, -2, 2, -1, 3];\n    assert_eq!(vec, expected);\n}\n"
  },
  {
    "path": "rayon-core/src/test.rs",
    "content": "#![cfg(test)]\n\nuse crate::{ThreadPoolBuildError, ThreadPoolBuilder};\nuse std::sync::atomic::{AtomicUsize, Ordering};\nuse std::sync::{Arc, Barrier};\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn worker_thread_index() {\n    let pool = ThreadPoolBuilder::new().num_threads(22).build().unwrap();\n    assert_eq!(pool.current_num_threads(), 22);\n    assert_eq!(pool.current_thread_index(), None);\n    let index = pool.install(|| pool.current_thread_index().unwrap());\n    assert!(index < 22);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn start_callback_called() {\n    let n_threads = 16;\n    let n_called = Arc::new(AtomicUsize::new(0));\n    // Wait for all the threads in the pool plus the one running tests.\n    let barrier = Arc::new(Barrier::new(n_threads + 1));\n\n    let b = Arc::clone(&barrier);\n    let nc = Arc::clone(&n_called);\n    let start_handler = move |_| {\n        nc.fetch_add(1, Ordering::SeqCst);\n        b.wait();\n    };\n\n    let conf = ThreadPoolBuilder::new()\n        .num_threads(n_threads)\n        .start_handler(start_handler);\n    let _ = conf.build().unwrap();\n\n    // Wait for all the threads to have been scheduled to run.\n    barrier.wait();\n\n    // The handler must have been called on every started thread.\n    assert_eq!(n_called.load(Ordering::SeqCst), n_threads);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn exit_callback_called() {\n    let n_threads = 16;\n    let n_called = Arc::new(AtomicUsize::new(0));\n    // Wait for all the threads in the pool plus the one running tests.\n    let barrier = Arc::new(Barrier::new(n_threads + 1));\n\n    let b = Arc::clone(&barrier);\n    let nc = Arc::clone(&n_called);\n    let exit_handler = move |_| {\n        nc.fetch_add(1, Ordering::SeqCst);\n        b.wait();\n    };\n\n    let conf = ThreadPoolBuilder::new()\n        .num_threads(n_threads)\n        .exit_handler(exit_handler);\n    {\n        let _ = conf.build().unwrap();\n        // Drop the pool so it stops the running threads.\n    }\n\n    // Wait for all the threads to have been scheduled to run.\n    barrier.wait();\n\n    // The handler must have been called on every exiting thread.\n    assert_eq!(n_called.load(Ordering::SeqCst), n_threads);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn handler_panics_handled_correctly() {\n    let n_threads = 16;\n    let n_called = Arc::new(AtomicUsize::new(0));\n    // Wait for all the threads in the pool plus the one running tests.\n    let start_barrier = Arc::new(Barrier::new(n_threads + 1));\n    let exit_barrier = Arc::new(Barrier::new(n_threads + 1));\n\n    let start_handler = move |_| {\n        panic!(\"ensure panic handler is called when starting\");\n    };\n    let exit_handler = move |_| {\n        panic!(\"ensure panic handler is called when exiting\");\n    };\n\n    let sb = Arc::clone(&start_barrier);\n    let eb = Arc::clone(&exit_barrier);\n    let nc = Arc::clone(&n_called);\n    let panic_handler = move |_| {\n        let val = nc.fetch_add(1, Ordering::SeqCst);\n        if val < n_threads {\n            sb.wait();\n        } else {\n            eb.wait();\n        }\n    };\n\n    let conf = ThreadPoolBuilder::new()\n        .num_threads(n_threads)\n        .start_handler(start_handler)\n        .exit_handler(exit_handler)\n        .panic_handler(panic_handler);\n    {\n        let _ = conf.build().unwrap();\n\n        // Wait for all the threads to start, panic in the start handler,\n        // and been taken care of by the panic handler.\n        start_barrier.wait();\n\n        // Drop the pool so it stops the running threads.\n    }\n\n    // Wait for all the threads to exit, panic in the exit handler,\n    // and been taken care of by the panic handler.\n    exit_barrier.wait();\n\n    // The panic handler must have been called twice on every thread.\n    assert_eq!(n_called.load(Ordering::SeqCst), 2 * n_threads);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn check_config_build() {\n    let pool = ThreadPoolBuilder::new().num_threads(22).build().unwrap();\n    assert_eq!(pool.current_num_threads(), 22);\n}\n\n/// Helper used by check_error_send_sync to ensure ThreadPoolBuildError is Send + Sync\nfn _send_sync<T: Send + Sync>() {}\n\n#[test]\nfn check_error_send_sync() {\n    _send_sync::<ThreadPoolBuildError>();\n}\n\n#[allow(deprecated)]\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn configuration() {\n    let start_handler = move |_| {};\n    let exit_handler = move |_| {};\n    let panic_handler = move |_| {};\n    let thread_name = move |i| format!(\"thread_name_{i}\");\n\n    // Ensure we can call all public methods on Configuration\n    crate::Configuration::new()\n        .thread_name(thread_name)\n        .num_threads(5)\n        .panic_handler(panic_handler)\n        .stack_size(4e6 as usize)\n        .breadth_first()\n        .start_handler(start_handler)\n        .exit_handler(exit_handler)\n        .build()\n        .unwrap();\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn default_pool() {\n    ThreadPoolBuilder::default().build().unwrap();\n}\n\n/// Test that custom spawned threads get their `WorkerThread` cleared once\n/// the pool is done with them, allowing them to be used with rayon again\n/// later. e.g. WebAssembly want to have their own pool of available threads.\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn cleared_current_thread() -> Result<(), ThreadPoolBuildError> {\n    let n_threads = 5;\n    let mut handles = vec![];\n    let pool = ThreadPoolBuilder::new()\n        .num_threads(n_threads)\n        .spawn_handler(|thread| {\n            let handle = std::thread::spawn(move || {\n                thread.run();\n\n                // Afterward, the current thread shouldn't be set anymore.\n                assert_eq!(crate::current_thread_index(), None);\n            });\n            handles.push(handle);\n            Ok(())\n        })\n        .build()?;\n    assert_eq!(handles.len(), n_threads);\n\n    pool.install(|| assert!(crate::current_thread_index().is_some()));\n    drop(pool);\n\n    // Wait for all threads to make their assertions and exit\n    for handle in handles {\n        handle.join().unwrap();\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "rayon-core/src/thread_pool/mod.rs",
    "content": "//! Contains support for user-managed thread pools, represented by the\n//! the [`ThreadPool`] type (see that struct for details).\n\nuse crate::broadcast::{self, BroadcastContext};\nuse crate::join;\nuse crate::registry::{Registry, ThreadSpawn, WorkerThread};\nuse crate::scope::{do_in_place_scope, do_in_place_scope_fifo};\nuse crate::spawn;\nuse crate::{scope, Scope};\nuse crate::{scope_fifo, ScopeFifo};\nuse crate::{ThreadPoolBuildError, ThreadPoolBuilder};\nuse std::error::Error;\nuse std::fmt;\nuse std::sync::Arc;\n\nmod test;\n\n/// Represents a user-created [thread pool].\n///\n/// Use a [`ThreadPoolBuilder`] to specify the number and/or names of threads\n/// in the pool. After calling [`ThreadPoolBuilder::build()`], you can then\n/// execute functions explicitly within this [`ThreadPool`] using\n/// [`ThreadPool::install()`]. By contrast, top-level rayon functions\n/// (like `join()`) will execute implicitly within the current thread pool.\n///\n///\n/// ## Creating a ThreadPool\n///\n/// ```ignore-wasm\n/// # use rayon_core as rayon;\n/// let pool = rayon::ThreadPoolBuilder::new().num_threads(8).build().unwrap();\n/// ```\n///\n/// [`install()`][`ThreadPool::install()`] executes a closure in one of the `ThreadPool`'s\n/// threads. In addition, any other rayon operations called inside of `install()` will also\n/// execute in the context of the `ThreadPool`.\n///\n/// When the `ThreadPool` is dropped, that's a signal for the threads it manages to terminate,\n/// they will complete executing any remaining work that you have spawned, and automatically\n/// terminate.\n///\n///\n/// [thread pool]: https://en.wikipedia.org/wiki/Thread_pool\n/// [`ThreadPoolBuilder::build()`]: ThreadPoolBuilder::build()\n/// [`ThreadPool::install()`]: Self::install()\npub struct ThreadPool {\n    registry: Arc<Registry>,\n}\n\nimpl ThreadPool {\n    #[deprecated(note = \"Use `ThreadPoolBuilder::build`\")]\n    #[allow(deprecated)]\n    /// Deprecated in favor of `ThreadPoolBuilder::build`.\n    pub fn new(configuration: crate::Configuration) -> Result<ThreadPool, Box<dyn Error>> {\n        Self::build(configuration.into_builder()).map_err(Box::from)\n    }\n\n    pub(super) fn build<S>(\n        builder: ThreadPoolBuilder<S>,\n    ) -> Result<ThreadPool, ThreadPoolBuildError>\n    where\n        S: ThreadSpawn,\n    {\n        let registry = Registry::new(builder)?;\n        Ok(ThreadPool { registry })\n    }\n\n    /// Executes `op` within the thread pool. Any attempts to use\n    /// `join`, `scope`, or parallel iterators will then operate\n    /// within that thread pool.\n    ///\n    /// # Warning: thread-local data\n    ///\n    /// Because `op` is executing within the Rayon thread pool,\n    /// thread-local data from the current thread will not be\n    /// accessible.\n    ///\n    /// # Warning: execution order\n    ///\n    /// If the current thread is part of a different thread pool, it will try to\n    /// keep busy while the `op` completes in its target pool, similar to\n    /// calling [`ThreadPool::yield_now()`] in a loop. Therefore, it may\n    /// potentially schedule other tasks to run on the current thread in the\n    /// meantime. For example\n    ///\n    /// ```ignore-wasm\n    /// # use rayon_core as rayon;\n    /// fn main() {\n    ///     rayon::ThreadPoolBuilder::new().num_threads(1).build_global().unwrap();\n    ///     let pool = rayon_core::ThreadPoolBuilder::default().build().unwrap();\n    ///     let do_it = || {\n    ///         print!(\"one \");\n    ///         pool.install(||{});\n    ///         print!(\"two \");\n    ///     };\n    ///     rayon::join(|| do_it(), || do_it());\n    /// }\n    /// ```\n    ///\n    /// Since we configured just one thread in the global pool, one might\n    /// expect `do_it()` to run sequentially, producing:\n    ///\n    /// ```ascii\n    /// one two one two\n    /// ```\n    ///\n    /// However each call to `install()` yields implicitly, allowing rayon to\n    /// run multiple instances of `do_it()` concurrently on the single, global\n    /// thread. The following output would be equally valid:\n    ///\n    /// ```ascii\n    /// one one two two\n    /// ```\n    ///\n    /// # Panics\n    ///\n    /// If `op` should panic, that panic will be propagated.\n    ///\n    /// ## Using `install()`\n    ///\n    /// ```ignore-wasm\n    ///    # use rayon_core as rayon;\n    ///    fn main() {\n    ///         let pool = rayon::ThreadPoolBuilder::new().num_threads(8).build().unwrap();\n    ///         let n = pool.install(|| fib(20));\n    ///         println!(\"{}\", n);\n    ///    }\n    ///\n    ///    fn fib(n: usize) -> usize {\n    ///         if n == 0 || n == 1 {\n    ///             return n;\n    ///         }\n    ///         let (a, b) = rayon::join(|| fib(n - 1), || fib(n - 2)); // runs inside of `pool`\n    ///         return a + b;\n    ///     }\n    /// ```\n    pub fn install<OP, R>(&self, op: OP) -> R\n    where\n        OP: FnOnce() -> R + Send,\n        R: Send,\n    {\n        self.registry.in_worker(|_, _| op())\n    }\n\n    /// Executes `op` within every thread in the thread pool. Any attempts to use\n    /// `join`, `scope`, or parallel iterators will then operate within that\n    /// thread pool.\n    ///\n    /// Broadcasts are executed on each thread after they have exhausted their\n    /// local work queue, before they attempt work-stealing from other threads.\n    /// The goal of that strategy is to run everywhere in a timely manner\n    /// *without* being too disruptive to current work. There may be alternative\n    /// broadcast styles added in the future for more or less aggressive\n    /// injection, if the need arises.\n    ///\n    /// # Warning: thread-local data\n    ///\n    /// Because `op` is executing within the Rayon thread pool,\n    /// thread-local data from the current thread will not be\n    /// accessible.\n    ///\n    /// # Panics\n    ///\n    /// If `op` should panic on one or more threads, exactly one panic\n    /// will be propagated, only after all threads have completed\n    /// (or panicked) their own `op`.\n    ///\n    /// # Examples\n    ///\n    /// ```ignore-wasm\n    ///    # use rayon_core as rayon;\n    ///    use std::sync::atomic::{AtomicUsize, Ordering};\n    ///\n    ///    fn main() {\n    ///         let pool = rayon::ThreadPoolBuilder::new().num_threads(5).build().unwrap();\n    ///\n    ///         // The argument gives context, including the index of each thread.\n    ///         let v: Vec<usize> = pool.broadcast(|ctx| ctx.index() * ctx.index());\n    ///         assert_eq!(v, &[0, 1, 4, 9, 16]);\n    ///\n    ///         // The closure can reference the local stack\n    ///         let count = AtomicUsize::new(0);\n    ///         pool.broadcast(|_| count.fetch_add(1, Ordering::Relaxed));\n    ///         assert_eq!(count.into_inner(), 5);\n    ///    }\n    /// ```\n    pub fn broadcast<OP, R>(&self, op: OP) -> Vec<R>\n    where\n        OP: Fn(BroadcastContext<'_>) -> R + Sync,\n        R: Send,\n    {\n        // We assert that `self.registry` has not terminated.\n        unsafe { broadcast::broadcast_in(op, &self.registry) }\n    }\n\n    /// Returns the (current) number of threads in the thread pool.\n    ///\n    /// # Future compatibility note\n    ///\n    /// Note that unless this thread pool was created with a\n    /// [`ThreadPoolBuilder`] that specifies the number of threads,\n    /// then this number may vary over time in future versions (see [the\n    /// `num_threads()` method for details][snt]).\n    ///\n    /// [snt]: ThreadPoolBuilder::num_threads()\n    #[inline]\n    pub fn current_num_threads(&self) -> usize {\n        self.registry.num_threads()\n    }\n\n    /// If called from a Rayon worker thread in this thread pool,\n    /// returns the index of that thread; if not called from a Rayon\n    /// thread, or called from a Rayon thread that belongs to a\n    /// different thread pool, returns `None`.\n    ///\n    /// The index for a given thread will not change over the thread's\n    /// lifetime. However, multiple threads may share the same index if\n    /// they are in distinct thread pools.\n    ///\n    /// # Future compatibility note\n    ///\n    /// Currently, every thread pool (including the global\n    /// thread pool) has a fixed number of threads, but this may\n    /// change in future Rayon versions (see [the `num_threads()` method\n    /// for details][snt]). In that case, the index for a\n    /// thread would not change during its lifetime, but thread\n    /// indices may wind up being reused if threads are terminated and\n    /// restarted.\n    ///\n    /// [snt]: ThreadPoolBuilder::num_threads()\n    #[inline]\n    pub fn current_thread_index(&self) -> Option<usize> {\n        let curr = self.registry.current_thread()?;\n        Some(curr.index())\n    }\n\n    /// Returns true if the current worker thread currently has \"local\n    /// tasks\" pending. This can be useful as part of a heuristic for\n    /// deciding whether to spawn a new task or execute code on the\n    /// current thread, particularly in breadth-first\n    /// schedulers. However, keep in mind that this is an inherently\n    /// racy check, as other worker threads may be actively \"stealing\"\n    /// tasks from our local deque.\n    ///\n    /// **Background:** Rayon's uses a [work-stealing] scheduler. The\n    /// key idea is that each thread has its own [deque] of\n    /// tasks. Whenever a new task is spawned -- whether through\n    /// `join()`, `Scope::spawn()`, or some other means -- that new\n    /// task is pushed onto the thread's *local* deque. Worker threads\n    /// have a preference for executing their own tasks; if however\n    /// they run out of tasks, they will go try to \"steal\" tasks from\n    /// other threads. This function therefore has an inherent race\n    /// with other active worker threads, which may be removing items\n    /// from the local deque.\n    ///\n    /// [work-stealing]: https://en.wikipedia.org/wiki/Work_stealing\n    /// [deque]: https://en.wikipedia.org/wiki/Double-ended_queue\n    #[inline]\n    pub fn current_thread_has_pending_tasks(&self) -> Option<bool> {\n        let curr = self.registry.current_thread()?;\n        Some(!curr.local_deque_is_empty())\n    }\n\n    /// Execute `oper_a` and `oper_b` in the thread pool and return\n    /// the results. Equivalent to `self.install(|| join(oper_a,\n    /// oper_b))`.\n    pub fn join<A, B, RA, RB>(&self, oper_a: A, oper_b: B) -> (RA, RB)\n    where\n        A: FnOnce() -> RA + Send,\n        B: FnOnce() -> RB + Send,\n        RA: Send,\n        RB: Send,\n    {\n        self.install(|| join(oper_a, oper_b))\n    }\n\n    /// Creates a scope that executes within this thread pool.\n    /// Equivalent to `self.install(|| scope(...))`.\n    ///\n    /// See also: [the `scope()` function].\n    ///\n    /// [the `scope()` function]: crate::scope()\n    pub fn scope<'scope, OP, R>(&self, op: OP) -> R\n    where\n        OP: FnOnce(&Scope<'scope>) -> R + Send,\n        R: Send,\n    {\n        self.install(|| scope(op))\n    }\n\n    /// Creates a scope that executes within this thread pool.\n    /// Spawns from the same thread are prioritized in relative FIFO order.\n    /// Equivalent to `self.install(|| scope_fifo(...))`.\n    ///\n    /// See also: [the `scope_fifo()` function].\n    ///\n    /// [the `scope_fifo()` function]: crate::scope_fifo()\n    pub fn scope_fifo<'scope, OP, R>(&self, op: OP) -> R\n    where\n        OP: FnOnce(&ScopeFifo<'scope>) -> R + Send,\n        R: Send,\n    {\n        self.install(|| scope_fifo(op))\n    }\n\n    /// Creates a scope that spawns work into this thread pool.\n    ///\n    /// See also: [the `in_place_scope()` function].\n    ///\n    /// [the `in_place_scope()` function]: crate::in_place_scope()\n    pub fn in_place_scope<'scope, OP, R>(&self, op: OP) -> R\n    where\n        OP: FnOnce(&Scope<'scope>) -> R,\n    {\n        do_in_place_scope(Some(&self.registry), op)\n    }\n\n    /// Creates a scope that spawns work into this thread pool in FIFO order.\n    ///\n    /// See also: [the `in_place_scope_fifo()` function].\n    ///\n    /// [the `in_place_scope_fifo()` function]: crate::in_place_scope_fifo()\n    pub fn in_place_scope_fifo<'scope, OP, R>(&self, op: OP) -> R\n    where\n        OP: FnOnce(&ScopeFifo<'scope>) -> R,\n    {\n        do_in_place_scope_fifo(Some(&self.registry), op)\n    }\n\n    /// Spawns an asynchronous task in this thread pool. This task will\n    /// run in the implicit, global scope, which means that it may outlast\n    /// the current stack frame -- therefore, it cannot capture any references\n    /// onto the stack (you will likely need a `move` closure).\n    ///\n    /// See also: [the `spawn()` function defined on scopes][spawn].\n    ///\n    /// [spawn]: Scope::spawn()\n    pub fn spawn<OP>(&self, op: OP)\n    where\n        OP: FnOnce() + Send + 'static,\n    {\n        // We assert that `self.registry` has not terminated.\n        unsafe { spawn::spawn_in(op, &self.registry) }\n    }\n\n    /// Spawns an asynchronous task in this thread pool. This task will\n    /// run in the implicit, global scope, which means that it may outlast\n    /// the current stack frame -- therefore, it cannot capture any references\n    /// onto the stack (you will likely need a `move` closure).\n    ///\n    /// See also: [the `spawn_fifo()` function defined on scopes][spawn_fifo].\n    ///\n    /// [spawn_fifo]: ScopeFifo::spawn_fifo()\n    pub fn spawn_fifo<OP>(&self, op: OP)\n    where\n        OP: FnOnce() + Send + 'static,\n    {\n        // We assert that `self.registry` has not terminated.\n        unsafe { spawn::spawn_fifo_in(op, &self.registry) }\n    }\n\n    /// Spawns an asynchronous task on every thread in this thread pool. This task\n    /// will run in the implicit, global scope, which means that it may outlast the\n    /// current stack frame -- therefore, it cannot capture any references onto the\n    /// stack (you will likely need a `move` closure).\n    pub fn spawn_broadcast<OP>(&self, op: OP)\n    where\n        OP: Fn(BroadcastContext<'_>) + Send + Sync + 'static,\n    {\n        // We assert that `self.registry` has not terminated.\n        unsafe { broadcast::spawn_broadcast_in(op, &self.registry) }\n    }\n\n    /// Cooperatively yields execution to Rayon.\n    ///\n    /// This is similar to the general [`yield_now()`], but only if the current\n    /// thread is part of *this* thread pool.\n    ///\n    /// Returns `Some(Yield::Executed)` if anything was executed, `Some(Yield::Idle)` if\n    /// nothing was available, or `None` if the current thread is not part this pool.\n    pub fn yield_now(&self) -> Option<Yield> {\n        let curr = self.registry.current_thread()?;\n        Some(curr.yield_now())\n    }\n\n    /// Cooperatively yields execution to local Rayon work.\n    ///\n    /// This is similar to the general [`yield_local()`], but only if the current\n    /// thread is part of *this* thread pool.\n    ///\n    /// Returns `Some(Yield::Executed)` if anything was executed, `Some(Yield::Idle)` if\n    /// nothing was available, or `None` if the current thread is not part this pool.\n    pub fn yield_local(&self) -> Option<Yield> {\n        let curr = self.registry.current_thread()?;\n        Some(curr.yield_local())\n    }\n}\n\nimpl Drop for ThreadPool {\n    fn drop(&mut self) {\n        self.registry.terminate();\n    }\n}\n\nimpl fmt::Debug for ThreadPool {\n    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt.debug_struct(\"ThreadPool\")\n            .field(\"num_threads\", &self.current_num_threads())\n            .field(\"id\", &self.registry.id())\n            .finish()\n    }\n}\n\n/// If called from a Rayon worker thread, returns the index of that\n/// thread within its current pool; if not called from a Rayon thread,\n/// returns `None`.\n///\n/// The index for a given thread will not change over the thread's\n/// lifetime. However, multiple threads may share the same index if\n/// they are in distinct thread pools.\n///\n/// See also: [the `ThreadPool::current_thread_index()` method][m].\n///\n/// [m]: ThreadPool::current_thread_index()\n///\n/// # Future compatibility note\n///\n/// Currently, every thread pool (including the global\n/// thread pool) has a fixed number of threads, but this may\n/// change in future Rayon versions (see [the `num_threads()` method\n/// for details][snt]). In that case, the index for a\n/// thread would not change during its lifetime, but thread\n/// indices may wind up being reused if threads are terminated and\n/// restarted.\n///\n/// [snt]: ThreadPoolBuilder::num_threads()\n#[inline]\npub fn current_thread_index() -> Option<usize> {\n    unsafe {\n        let curr = WorkerThread::current().as_ref()?;\n        Some(curr.index())\n    }\n}\n\n/// If called from a Rayon worker thread, indicates whether that\n/// thread's local deque still has pending tasks. Otherwise, returns\n/// `None`. For more information, see [the\n/// `ThreadPool::current_thread_has_pending_tasks()` method][m].\n///\n/// [m]: ThreadPool::current_thread_has_pending_tasks()\n#[inline]\npub fn current_thread_has_pending_tasks() -> Option<bool> {\n    unsafe {\n        let curr = WorkerThread::current().as_ref()?;\n        Some(!curr.local_deque_is_empty())\n    }\n}\n\n/// Cooperatively yields execution to Rayon.\n///\n/// If the current thread is part of a rayon thread pool, this looks for a\n/// single unit of pending work in the pool, then executes it. Completion of\n/// that work might include nested work or further work stealing.\n///\n/// This is similar to [`std::thread::yield_now()`], but does not literally make\n/// that call. If you are implementing a polling loop, you may want to also\n/// yield to the OS scheduler yourself if no Rayon work was found.\n///\n/// Returns `Some(Yield::Executed)` if anything was executed, `Some(Yield::Idle)` if\n/// nothing was available, or `None` if this thread is not part of any pool at all.\npub fn yield_now() -> Option<Yield> {\n    unsafe {\n        let thread = WorkerThread::current().as_ref()?;\n        Some(thread.yield_now())\n    }\n}\n\n/// Cooperatively yields execution to local Rayon work.\n///\n/// If the current thread is part of a rayon thread pool, this looks for a\n/// single unit of pending work in this thread's queue, then executes it.\n/// Completion of that work might include nested work or further work stealing.\n///\n/// This is similar to [`yield_now()`], but does not steal from other threads.\n///\n/// Returns `Some(Yield::Executed)` if anything was executed, `Some(Yield::Idle)` if\n/// nothing was available, or `None` if this thread is not part of any pool at all.\npub fn yield_local() -> Option<Yield> {\n    unsafe {\n        let thread = WorkerThread::current().as_ref()?;\n        Some(thread.yield_local())\n    }\n}\n\n/// Result of [`yield_now()`] or [`yield_local()`].\n#[derive(Clone, Copy, Debug, PartialEq, Eq)]\npub enum Yield {\n    /// Work was found and executed.\n    Executed,\n    /// No available work was found.\n    Idle,\n}\n"
  },
  {
    "path": "rayon-core/src/thread_pool/test.rs",
    "content": "#![cfg(test)]\n\nuse std::sync::atomic::{AtomicUsize, Ordering};\nuse std::sync::mpsc::channel;\nuse std::sync::{Arc, Mutex};\n\nuse crate::{join, Scope, ScopeFifo, ThreadPool, ThreadPoolBuilder};\n\n#[test]\n#[should_panic(expected = \"Hello, world!\")]\nfn panic_propagate() {\n    let thread_pool = ThreadPoolBuilder::new().build().unwrap();\n    thread_pool.install(|| {\n        panic!(\"Hello, world!\");\n    });\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn workers_stop() {\n    let registry;\n\n    {\n        // once we exit this block, thread pool will be dropped\n        let thread_pool = ThreadPoolBuilder::new().num_threads(22).build().unwrap();\n        registry = thread_pool.install(|| {\n            // do some work on these threads\n            join_a_lot(22);\n\n            Arc::clone(&thread_pool.registry)\n        });\n        assert_eq!(registry.num_threads(), 22);\n    }\n\n    // once thread pool is dropped, registry should terminate, which\n    // should lead to worker threads stopping\n    registry.wait_until_stopped();\n}\n\nfn join_a_lot(n: usize) {\n    if n > 0 {\n        join(|| join_a_lot(n - 1), || join_a_lot(n - 1));\n    }\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn sleeper_stop() {\n    use std::{thread, time};\n\n    let registry;\n\n    {\n        // once we exit this block, thread pool will be dropped\n        let thread_pool = ThreadPoolBuilder::new().num_threads(22).build().unwrap();\n        registry = Arc::clone(&thread_pool.registry);\n\n        // Give time for at least some of the thread pool to fall asleep.\n        thread::sleep(time::Duration::from_secs(1));\n    }\n\n    // once thread pool is dropped, registry should terminate, which\n    // should lead to worker threads stopping\n    registry.wait_until_stopped();\n}\n\n/// Creates a start/exit handler that increments an atomic counter.\nfn count_handler() -> (Arc<AtomicUsize>, impl Fn(usize)) {\n    let count = Arc::new(AtomicUsize::new(0));\n    (Arc::clone(&count), move |_| {\n        count.fetch_add(1, Ordering::SeqCst);\n    })\n}\n\n/// Wait until a counter is no longer shared, then return its value.\nfn wait_for_counter(mut counter: Arc<AtomicUsize>) -> usize {\n    use std::{thread, time};\n\n    for _ in 0..60 {\n        counter = match Arc::try_unwrap(counter) {\n            Ok(counter) => return counter.into_inner(),\n            Err(counter) => {\n                thread::sleep(time::Duration::from_secs(1));\n                counter\n            }\n        };\n    }\n\n    // That's too long!\n    panic!(\"Counter is still shared!\");\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn failed_thread_stack() {\n    // Note: we first tried to force failure with a `usize::MAX` stack, but\n    // macOS and Windows weren't fazed, or at least didn't fail the way we want.\n    // They work with `isize::MAX`, but 32-bit platforms may feasibly allocate a\n    // 2GB stack, so it might not fail until the second thread.\n    let stack_size = isize::MAX as usize;\n\n    let (start_count, start_handler) = count_handler();\n    let (exit_count, exit_handler) = count_handler();\n    let builder = ThreadPoolBuilder::new()\n        .num_threads(10)\n        .stack_size(stack_size)\n        .start_handler(start_handler)\n        .exit_handler(exit_handler);\n\n    let pool = builder.build();\n    assert!(pool.is_err(), \"thread stack should have failed!\");\n\n    // With such a huge stack, 64-bit will probably fail on the first thread;\n    // 32-bit might manage the first 2GB, but certainly fail the second.\n    let start_count = wait_for_counter(start_count);\n    assert!(start_count <= 1);\n    assert_eq!(start_count, wait_for_counter(exit_count));\n}\n\n#[test]\n#[cfg_attr(not(panic = \"unwind\"), ignore)]\nfn panic_thread_name() {\n    let (start_count, start_handler) = count_handler();\n    let (exit_count, exit_handler) = count_handler();\n    let builder = ThreadPoolBuilder::new()\n        .num_threads(10)\n        .start_handler(start_handler)\n        .exit_handler(exit_handler)\n        .thread_name(|i| {\n            if i >= 5 {\n                panic!();\n            }\n            format!(\"panic_thread_name#{i}\")\n        });\n\n    let pool = crate::unwind::halt_unwinding(|| builder.build());\n    assert!(pool.is_err(), \"thread-name panic should propagate!\");\n\n    // Assuming they're created in order, threads 0 through 4 should have\n    // been started already, and then terminated by the panic.\n    assert_eq!(5, wait_for_counter(start_count));\n    assert_eq!(5, wait_for_counter(exit_count));\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn self_install() {\n    let pool = ThreadPoolBuilder::new().num_threads(1).build().unwrap();\n\n    // If the inner `install` blocks, then nothing will actually run it!\n    assert!(pool.install(|| pool.install(|| true)));\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn mutual_install() {\n    let pool1 = ThreadPoolBuilder::new().num_threads(1).build().unwrap();\n    let pool2 = ThreadPoolBuilder::new().num_threads(1).build().unwrap();\n\n    let ok = pool1.install(|| {\n        // This creates a dependency from `pool1` -> `pool2`\n        pool2.install(|| {\n            // This creates a dependency from `pool2` -> `pool1`\n            pool1.install(|| {\n                // If they blocked on inter-pool installs, there would be no\n                // threads left to run this!\n                true\n            })\n        })\n    });\n    assert!(ok);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn mutual_install_sleepy() {\n    use std::{thread, time};\n\n    let pool1 = ThreadPoolBuilder::new().num_threads(1).build().unwrap();\n    let pool2 = ThreadPoolBuilder::new().num_threads(1).build().unwrap();\n\n    let ok = pool1.install(|| {\n        // This creates a dependency from `pool1` -> `pool2`\n        pool2.install(|| {\n            // Give `pool1` time to fall asleep.\n            thread::sleep(time::Duration::from_secs(1));\n\n            // This creates a dependency from `pool2` -> `pool1`\n            pool1.install(|| {\n                // Give `pool2` time to fall asleep.\n                thread::sleep(time::Duration::from_secs(1));\n\n                // If they blocked on inter-pool installs, there would be no\n                // threads left to run this!\n                true\n            })\n        })\n    });\n    assert!(ok);\n}\n\n#[test]\n#[allow(deprecated)]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn check_thread_pool_new() {\n    let pool = ThreadPool::new(crate::Configuration::new().num_threads(22)).unwrap();\n    assert_eq!(pool.current_num_threads(), 22);\n}\n\nmacro_rules! test_scope_order {\n    ($scope:ident => $spawn:ident) => {{\n        let builder = ThreadPoolBuilder::new().num_threads(1);\n        let pool = builder.build().unwrap();\n        pool.install(|| {\n            let vec = Mutex::new(vec![]);\n            pool.$scope(|scope| {\n                let vec = &vec;\n                for i in 0..10 {\n                    scope.$spawn(move |_| {\n                        vec.lock().unwrap().push(i);\n                    });\n                }\n            });\n            vec.into_inner().unwrap()\n        })\n    }};\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn scope_lifo_order() {\n    let vec = test_scope_order!(scope => spawn);\n    let expected: Vec<i32> = (0..10).rev().collect(); // LIFO -> reversed\n    assert_eq!(vec, expected);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn scope_fifo_order() {\n    let vec = test_scope_order!(scope_fifo => spawn_fifo);\n    let expected: Vec<i32> = (0..10).collect(); // FIFO -> natural order\n    assert_eq!(vec, expected);\n}\n\nmacro_rules! test_spawn_order {\n    ($spawn:ident) => {{\n        let builder = ThreadPoolBuilder::new().num_threads(1);\n        let pool = &builder.build().unwrap();\n        let (tx, rx) = channel();\n        pool.install(move || {\n            for i in 0..10 {\n                let tx = tx.clone();\n                pool.$spawn(move || {\n                    tx.send(i).unwrap();\n                });\n            }\n        });\n        rx.iter().collect::<Vec<i32>>()\n    }};\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn spawn_lifo_order() {\n    let vec = test_spawn_order!(spawn);\n    let expected: Vec<i32> = (0..10).rev().collect(); // LIFO -> reversed\n    assert_eq!(vec, expected);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn spawn_fifo_order() {\n    let vec = test_spawn_order!(spawn_fifo);\n    let expected: Vec<i32> = (0..10).collect(); // FIFO -> natural order\n    assert_eq!(vec, expected);\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn nested_scopes() {\n    // Create matching scopes for every thread pool.\n    fn nest<'scope, OP>(pools: &[ThreadPool], scopes: Vec<&Scope<'scope>>, op: OP)\n    where\n        OP: FnOnce(&[&Scope<'scope>]) + Send,\n    {\n        if let Some((pool, tail)) = pools.split_first() {\n            pool.scope(move |s| {\n                // This move reduces the reference lifetimes by variance to match s,\n                // but the actual scopes are still tied to the invariant 'scope.\n                let mut scopes = scopes;\n                scopes.push(s);\n                nest(tail, scopes, op)\n            })\n        } else {\n            (op)(&scopes)\n        }\n    }\n\n    let pools: Vec<_> = (0..10)\n        .map(|_| ThreadPoolBuilder::new().num_threads(1).build().unwrap())\n        .collect();\n\n    let counter = AtomicUsize::new(0);\n    nest(&pools, vec![], |scopes| {\n        for &s in scopes {\n            s.spawn(|_| {\n                // Our 'scope lets us borrow the counter in every pool.\n                counter.fetch_add(1, Ordering::Relaxed);\n            });\n        }\n    });\n    assert_eq!(counter.into_inner(), pools.len());\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn nested_fifo_scopes() {\n    // Create matching fifo scopes for every thread pool.\n    fn nest<'scope, OP>(pools: &[ThreadPool], scopes: Vec<&ScopeFifo<'scope>>, op: OP)\n    where\n        OP: FnOnce(&[&ScopeFifo<'scope>]) + Send,\n    {\n        if let Some((pool, tail)) = pools.split_first() {\n            pool.scope_fifo(move |s| {\n                // This move reduces the reference lifetimes by variance to match s,\n                // but the actual scopes are still tied to the invariant 'scope.\n                let mut scopes = scopes;\n                scopes.push(s);\n                nest(tail, scopes, op)\n            })\n        } else {\n            (op)(&scopes)\n        }\n    }\n\n    let pools: Vec<_> = (0..10)\n        .map(|_| ThreadPoolBuilder::new().num_threads(1).build().unwrap())\n        .collect();\n\n    let counter = AtomicUsize::new(0);\n    nest(&pools, vec![], |scopes| {\n        for &s in scopes {\n            s.spawn_fifo(|_| {\n                // Our 'scope lets us borrow the counter in every pool.\n                counter.fetch_add(1, Ordering::Relaxed);\n            });\n        }\n    });\n    assert_eq!(counter.into_inner(), pools.len());\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn in_place_scope_no_deadlock() {\n    let pool = ThreadPoolBuilder::new().num_threads(1).build().unwrap();\n    let (tx, rx) = channel();\n    let rx_ref = &rx;\n    pool.in_place_scope(move |s| {\n        // With regular scopes this closure would never run because this scope op\n        // itself would block the only worker thread.\n        s.spawn(move |_| {\n            tx.send(()).unwrap();\n        });\n        rx_ref.recv().unwrap();\n    });\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn in_place_scope_fifo_no_deadlock() {\n    let pool = ThreadPoolBuilder::new().num_threads(1).build().unwrap();\n    let (tx, rx) = channel();\n    let rx_ref = &rx;\n    pool.in_place_scope_fifo(move |s| {\n        // With regular scopes this closure would never run because this scope op\n        // itself would block the only worker thread.\n        s.spawn_fifo(move |_| {\n            tx.send(()).unwrap();\n        });\n        rx_ref.recv().unwrap();\n    });\n}\n\n#[test]\nfn yield_now_to_spawn() {\n    let (tx, rx) = channel();\n\n    // Queue a regular spawn.\n    crate::spawn(move || tx.send(22).unwrap());\n\n    // The single-threaded fallback mode (for wasm etc.) won't\n    // get a chance to run the spawn if we never yield to it.\n    crate::registry::in_worker(move |_, _| {\n        crate::yield_now();\n    });\n\n    // The spawn **must** have started by now, but we still might have to wait\n    // for it to finish if a different thread stole it first.\n    assert_eq!(22, rx.recv().unwrap());\n}\n\n#[test]\nfn yield_local_to_spawn() {\n    let (tx, rx) = channel();\n\n    // Queue a regular spawn.\n    crate::spawn(move || tx.send(22).unwrap());\n\n    // The single-threaded fallback mode (for wasm etc.) won't\n    // get a chance to run the spawn if we never yield to it.\n    crate::registry::in_worker(move |_, _| {\n        crate::yield_local();\n    });\n\n    // The spawn **must** have started by now, but we still might have to wait\n    // for it to finish if a different thread stole it first.\n    assert_eq!(22, rx.recv().unwrap());\n}\n"
  },
  {
    "path": "rayon-core/src/unwind.rs",
    "content": "//! Package up unwind recovery. Note that if you are in some sensitive\n//! place, you can use the `AbortIfPanic` helper to protect against\n//! accidental panics in the rayon code itself.\n\nuse std::any::Any;\nuse std::panic::{self, AssertUnwindSafe};\nuse std::thread;\n\n/// Executes `f` and captures any panic, translating that panic into a\n/// `Err` result. The assumption is that any panic will be propagated\n/// later with `resume_unwinding`, and hence `f` can be treated as\n/// exception safe.\npub(super) fn halt_unwinding<F, R>(func: F) -> thread::Result<R>\nwhere\n    F: FnOnce() -> R,\n{\n    panic::catch_unwind(AssertUnwindSafe(func))\n}\n\npub(super) fn resume_unwinding(payload: Box<dyn Any + Send>) -> ! {\n    panic::resume_unwind(payload)\n}\n\npub(super) struct AbortIfPanic;\n\nimpl Drop for AbortIfPanic {\n    fn drop(&mut self) {\n        eprintln!(\"Rayon: detected unexpected panic; aborting\");\n        ::std::process::abort();\n    }\n}\n"
  },
  {
    "path": "rayon-core/tests/double_init_fail.rs",
    "content": "use rayon_core::ThreadPoolBuilder;\nuse std::error::Error;\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn double_init_fail() {\n    let result1 = ThreadPoolBuilder::new().build_global();\n    assert!(result1.is_ok());\n    let err = ThreadPoolBuilder::new().build_global().unwrap_err();\n    assert!(err.source().is_none());\n    assert_eq!(\n        err.to_string(),\n        \"The global thread pool has already been initialized.\",\n    );\n}\n"
  },
  {
    "path": "rayon-core/tests/init_zero_threads.rs",
    "content": "use rayon_core::ThreadPoolBuilder;\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn init_zero_threads() {\n    ThreadPoolBuilder::new()\n        .num_threads(0)\n        .build_global()\n        .unwrap();\n}\n"
  },
  {
    "path": "rayon-core/tests/scope_join.rs",
    "content": "/// Test that one can emulate join with `scope`:\nfn pseudo_join<F, G>(f: F, g: G)\nwhere\n    F: FnOnce() + Send,\n    G: FnOnce() + Send,\n{\n    rayon_core::scope(|s| {\n        s.spawn(|_| g());\n        f();\n    });\n}\n\nfn quick_sort<T: PartialOrd + Send>(v: &mut [T]) {\n    if v.len() <= 1 {\n        return;\n    }\n\n    let mid = partition(v);\n    let (lo, hi) = v.split_at_mut(mid);\n    pseudo_join(|| quick_sort(lo), || quick_sort(hi));\n}\n\nfn partition<T: PartialOrd + Send>(v: &mut [T]) -> usize {\n    let pivot = v.len() - 1;\n    let mut i = 0;\n    for j in 0..pivot {\n        if v[j] <= v[pivot] {\n            v.swap(i, j);\n            i += 1;\n        }\n    }\n    v.swap(i, pivot);\n    i\n}\n\nfn is_sorted<T: Send + Ord>(v: &[T]) -> bool {\n    (1..v.len()).all(|i| v[i - 1] <= v[i])\n}\n\n#[test]\nfn scope_join() {\n    let mut v: Vec<i32> = (0..256).rev().collect();\n    quick_sort(&mut v);\n    assert!(is_sorted(&v));\n}\n"
  },
  {
    "path": "rayon-core/tests/scoped_threadpool.rs",
    "content": "use crossbeam_utils::thread;\nuse rayon_core::ThreadPoolBuilder;\n\n#[derive(PartialEq, Eq, Debug)]\nstruct Local(i32);\n\nscoped_tls::scoped_thread_local!(static LOCAL: Local);\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn missing_scoped_tls() {\n    LOCAL.set(&Local(42), || {\n        let pool = ThreadPoolBuilder::new()\n            .build()\n            .expect(\"thread pool created\");\n\n        // `LOCAL` is not set in the pool.\n        pool.install(|| {\n            assert!(!LOCAL.is_set());\n        });\n    });\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn spawn_scoped_tls_threadpool() {\n    LOCAL.set(&Local(42), || {\n        LOCAL.with(|x| {\n            thread::scope(|scope| {\n                let pool = ThreadPoolBuilder::new()\n                    .spawn_handler(move |thread| {\n                        scope\n                            .builder()\n                            .spawn(move |_| {\n                                // Borrow the same local value in the thread pool.\n                                LOCAL.set(x, || thread.run())\n                            })\n                            .map(|_| ())\n                    })\n                    .build()\n                    .expect(\"thread pool created\");\n\n                // The pool matches our local value.\n                pool.install(|| {\n                    assert!(LOCAL.is_set());\n                    LOCAL.with(|y| {\n                        assert_eq!(x, y);\n                    });\n                });\n\n                // If we change our local value, the pool is not affected.\n                LOCAL.set(&Local(-1), || {\n                    pool.install(|| {\n                        assert!(LOCAL.is_set());\n                        LOCAL.with(|y| {\n                            assert_eq!(x, y);\n                        });\n                    });\n                });\n            })\n            .expect(\"scope threads ok\");\n            // `thread::scope` will wait for the threads to exit before returning.\n        });\n    });\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn build_scoped_tls_threadpool() {\n    LOCAL.set(&Local(42), || {\n        LOCAL.with(|x| {\n            ThreadPoolBuilder::new()\n                .build_scoped(\n                    move |thread| LOCAL.set(x, || thread.run()),\n                    |pool| {\n                        // The pool matches our local value.\n                        pool.install(|| {\n                            assert!(LOCAL.is_set());\n                            LOCAL.with(|y| {\n                                assert_eq!(x, y);\n                            });\n                        });\n\n                        // If we change our local value, the pool is not affected.\n                        LOCAL.set(&Local(-1), || {\n                            pool.install(|| {\n                                assert!(LOCAL.is_set());\n                                LOCAL.with(|y| {\n                                    assert_eq!(x, y);\n                                });\n                            });\n                        });\n                    },\n                )\n                .expect(\"thread pool created\");\n            // Internally, `std::thread::scope` will wait for the threads to exit before returning.\n        });\n    });\n}\n"
  },
  {
    "path": "rayon-core/tests/simple_panic.rs",
    "content": "use rayon_core::join;\n\n#[test]\n#[should_panic(expected = \"should panic\")]\nfn simple_panic() {\n    join(|| {}, || panic!(\"should panic\"));\n}\n"
  },
  {
    "path": "rayon-core/tests/stack_overflow_crash.rs",
    "content": "use rayon_core::ThreadPoolBuilder;\n\nuse std::env;\nuse std::process::{Command, ExitStatus, Stdio};\n\n#[cfg(target_os = \"linux\")]\nuse std::os::unix::process::ExitStatusExt;\n\nfn force_stack_overflow(depth: u32) {\n    let mut buffer = [0u8; 1024 * 1024];\n    std::hint::black_box(&mut buffer);\n    if depth > 0 {\n        force_stack_overflow(depth - 1);\n    }\n}\n\n#[cfg(unix)]\nfn disable_core() {\n    unsafe {\n        libc::setrlimit(\n            libc::RLIMIT_CORE,\n            &libc::rlimit {\n                rlim_cur: 0,\n                rlim_max: 0,\n            },\n        );\n    }\n}\n\n#[cfg(unix)]\nfn overflow_code() -> Option<i32> {\n    None\n}\n\n#[cfg(windows)]\nfn overflow_code() -> Option<i32> {\n    use std::os::windows::process::ExitStatusExt;\n\n    ExitStatus::from_raw(0xc00000fd /*STATUS_STACK_OVERFLOW*/).code()\n}\n\n#[test]\n#[cfg_attr(not(any(unix, windows)), ignore)]\nfn stack_overflow_crash() {\n    // First check that the recursive call actually causes a stack overflow,\n    // and does not get optimized away.\n    let status = run_ignored(\"run_with_small_stack\");\n    assert!(!status.success());\n    #[cfg(any(unix, windows))]\n    assert_eq!(status.code(), overflow_code());\n    #[cfg(target_os = \"linux\")]\n    assert!(matches!(\n        status.signal(),\n        Some(libc::SIGABRT | libc::SIGSEGV)\n    ));\n\n    // Now run with a larger stack and verify correct operation.\n    let status = run_ignored(\"run_with_large_stack\");\n    assert_eq!(status.code(), Some(0));\n    #[cfg(target_os = \"linux\")]\n    assert_eq!(status.signal(), None);\n}\n\nfn run_ignored(test: &str) -> ExitStatus {\n    Command::new(env::current_exe().unwrap())\n        .arg(\"--ignored\")\n        .arg(\"--exact\")\n        .arg(test)\n        .stdout(Stdio::null())\n        .stderr(Stdio::null())\n        .status()\n        .unwrap()\n}\n\n#[test]\n#[ignore]\nfn run_with_small_stack() {\n    run_with_stack(8);\n}\n\n#[test]\n#[ignore]\nfn run_with_large_stack() {\n    run_with_stack(48);\n}\n\nfn run_with_stack(stack_size_in_mb: usize) {\n    let pool = ThreadPoolBuilder::new()\n        .stack_size(stack_size_in_mb * 1024 * 1024)\n        .build()\n        .unwrap();\n    pool.install(|| {\n        #[cfg(unix)]\n        disable_core();\n        force_stack_overflow(32);\n    });\n}\n"
  },
  {
    "path": "rayon-core/tests/use_current_thread.rs",
    "content": "use rayon_core::ThreadPoolBuilder;\nuse std::sync::{Arc, Condvar, Mutex};\nuse std::thread::{self, JoinHandle};\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn use_current_thread_basic() {\n    static JOIN_HANDLES: Mutex<Vec<JoinHandle<()>>> = Mutex::new(Vec::new());\n    let pool = ThreadPoolBuilder::new()\n        .num_threads(2)\n        .use_current_thread()\n        .spawn_handler(|builder| {\n            let handle = thread::Builder::new().spawn(|| builder.run())?;\n            JOIN_HANDLES.lock().unwrap().push(handle);\n            Ok(())\n        })\n        .build()\n        .unwrap();\n    assert_eq!(rayon_core::current_thread_index(), Some(0));\n    assert_eq!(\n        JOIN_HANDLES.lock().unwrap().len(),\n        1,\n        \"Should only spawn one extra thread\"\n    );\n\n    let another_pool = ThreadPoolBuilder::new()\n        .num_threads(2)\n        .use_current_thread()\n        .build();\n    assert!(\n        another_pool.is_err(),\n        \"Should error if the thread is already part of a pool\"\n    );\n\n    let pair = Arc::new((Mutex::new(false), Condvar::new()));\n    let pair2 = Arc::clone(&pair);\n    pool.spawn(move || {\n        assert_ne!(rayon_core::current_thread_index(), Some(0));\n        // This should execute even if the current thread is blocked, since we have two threads in\n        // the pool.\n        let (started, condvar) = &*pair2;\n        *started.lock().unwrap() = true;\n        condvar.notify_one();\n    });\n\n    let _guard = pair\n        .1\n        .wait_while(pair.0.lock().unwrap(), |ran| !*ran)\n        .unwrap();\n    std::mem::drop(pool); // Drop the pool.\n\n    // Wait until all threads have actually exited. This is not really needed, other than to\n    // reduce noise of leak-checking tools.\n    for handle in std::mem::take(&mut *JOIN_HANDLES.lock().unwrap()) {\n        let _ = handle.join();\n    }\n}\n"
  },
  {
    "path": "rayon-demo/Cargo.toml",
    "content": "[package]\nname = \"rayon-demo\"\npublish = false\n\nedition.workspace = true\nrust-version.workspace = true\n\n[dependencies]\nrayon = { path = \"../\" }\ncgmath = \"0.18\"\ndocopt = \"1\"\nfixedbitset = \"0.5\"\nglium = \"0.36\"\nrand.workspace = true\nrand_xorshift.workspace = true\nregex = \"1\"\nwinit = \"0.30\"\n\n[dependencies.serde]\nversion = \"1.0.85\"\nfeatures = [\"derive\"]\n\n[target.'cfg(unix)'.dependencies]\nlibc.workspace = true\n\n[target.'cfg(windows)'.dependencies]\nwinapi = { version = \"0.3\", features = [\"processthreadsapi\"] }\n\n[dev-dependencies]\ndoc-comment = \"0.3\"\nnum = \"0.4\"\n"
  },
  {
    "path": "rayon-demo/data/README.md",
    "content": "Data for various benchmarks. All in public domain or otherwise freely\nlicensed.\n"
  },
  {
    "path": "rayon-demo/data/tsp/README.md",
    "content": "Inputs for the Traveling Salesman Problem solver. These are in TSPLIB\nformat.\n\nSources:\n\n- `dj10.tsp`: derived from `dj38.tsp`\n- `dj15.tsp`: derived from `dj38.tsp`\n- `dj38.tsp`: <https://www.math.uwaterloo.ca/tsp/world/dj38.tsp>\n\n"
  },
  {
    "path": "rayon-demo/data/tsp/dj10.tsp",
    "content": "NAME: dj10\nCOMMENT : 10 locations in Djibouti; chosen from dj38.tsp\nTYPE: TSP\nDIMENSION: 10\nEDGE_WEIGHT_TYPE: EUC_2D\nNODE_COORD_SECTION\n1 11003.611100 42102.500000\n2 11108.611100 42373.888900\n3 11133.333300 42885.833300\n4 11155.833300 42712.500000\n5 11183.333300 42933.333300\n6 11297.500000 42853.333300\n7 11310.277800 42929.444400\n8 11416.666700 42983.333300\n9 11423.888900 43000.277800\n10 11438.333300 42057.222200\n"
  },
  {
    "path": "rayon-demo/data/tsp/dj15.tsp",
    "content": "NAME: dj15\nCOMMENT : 15 locations in Djibouti; chosen from dj38.tsp\nTYPE: TSP\nDIMENSION: 15\nEDGE_WEIGHT_TYPE: EUC_2D\nNODE_COORD_SECTION\n1 11003.611100 42102.500000\n2 11108.611100 42373.888900\n3 11133.333300 42885.833300\n4 11155.833300 42712.500000\n5 11183.333300 42933.333300\n6 11297.500000 42853.333300\n7 11310.277800 42929.444400\n8 11416.666700 42983.333300\n9 11423.888900 43000.277800\n10 11438.333300 42057.222200\n11 11461.111100 43252.777800\n12 11485.555600 43187.222200\n13 11503.055600 42855.277800\n14 11511.388900 42106.388900\n15 11522.222200 42841.944400\n"
  },
  {
    "path": "rayon-demo/data/tsp/dj38.tsp",
    "content": "NAME: dj38\nCOMMENT : 38 locations in Djibouti\nCOMMENT : Derived from National Imagery and Mapping Agency data\nCOMMENT : This file is a corrected version of dj89, where duplications\nCOMMENT:  have been removed.  Thanks to Jay Muthuswamy and others for\nCOMMENT:  requesting data sets without duplications.\nTYPE: TSP\nDIMENSION: 38\nEDGE_WEIGHT_TYPE: EUC_2D\nNODE_COORD_SECTION\n1 11003.611100 42102.500000\n2 11108.611100 42373.888900\n3 11133.333300 42885.833300\n4 11155.833300 42712.500000\n5 11183.333300 42933.333300\n6 11297.500000 42853.333300\n7 11310.277800 42929.444400\n8 11416.666700 42983.333300\n9 11423.888900 43000.277800\n10 11438.333300 42057.222200\n11 11461.111100 43252.777800\n12 11485.555600 43187.222200\n13 11503.055600 42855.277800\n14 11511.388900 42106.388900\n15 11522.222200 42841.944400\n16 11569.444400 43136.666700\n17 11583.333300 43150.000000\n18 11595.000000 43148.055600\n19 11600.000000 43150.000000\n20 11690.555600 42686.666700\n21 11715.833300 41836.111100\n22 11751.111100 42814.444400\n23 11770.277800 42651.944400\n24 11785.277800 42884.444400\n25 11822.777800 42673.611100\n26 11846.944400 42660.555600\n27 11963.055600 43290.555600\n28 11973.055600 43026.111100\n29 12058.333300 42195.555600\n30 12149.444400 42477.500000\n31 12286.944400 43355.555600\n32 12300.000000 42433.333300\n33 12355.833300 43156.388900\n34 12363.333300 43189.166700\n35 12372.777800 42711.388900\n36 12386.666700 43334.722200\n37 12421.666700 42895.555600\n38 12645.000000 42973.333300\n"
  },
  {
    "path": "rayon-demo/examples/README.md",
    "content": "We use this directory for interactive tests that can't be run in an\nautomatic fashion. For examples of how to use Rayon, or benchmarks,\nsee `rayon-demo`.\n"
  },
  {
    "path": "rayon-demo/examples/cpu_monitor.rs",
    "content": "use docopt::Docopt;\nuse std::io;\nuse std::process;\n\nconst USAGE: &str = \"\nUsage: cpu_monitor [options] <scenario>\n       cpu_monitor --help\n\nA test for monitoring how much CPU usage Rayon consumes under various\nscenarios. This test is intended to be executed interactively, like so:\n\n    cargo run --example cpu_monitor -- tasks_ended\n\nThe list of scenarios you can try are as follows:\n\n- tasks_ended: after all tasks have finished, go to sleep\n- task_stall_root: a root task stalls for a very long time\n- task_stall_scope: a task in a scope stalls for a very long time\n\nOptions:\n    -h, --help                   Show this message.\n    -d N, --depth N              Control how hard the dummy task works [default: 27]\n\";\n\n#[derive(serde::Deserialize)]\npub struct Args {\n    arg_scenario: String,\n    flag_depth: usize,\n}\n\nfn main() {\n    let args: &Args = &Docopt::new(USAGE)\n        .and_then(|d| d.deserialize())\n        .unwrap_or_else(|e| e.exit());\n\n    match &args.arg_scenario[..] {\n        \"tasks_ended\" => tasks_ended(args),\n        \"task_stall_root\" => task_stall_root(args),\n        \"task_stall_scope\" => task_stall_scope(args),\n        _ => {\n            println!(\"unknown scenario: `{}`\", args.arg_scenario);\n            println!(\"try --help\");\n            process::exit(1);\n        }\n    }\n}\n\nfn wait_for_user() {\n    let mut input = String::new();\n    io::stdin().read_line(&mut input).unwrap();\n}\n\nfn task(args: &Args) {\n    fn join_recursively(n: usize) {\n        if n == 0 {\n            return;\n        }\n        rayon::join(|| join_recursively(n - 1), || join_recursively(n - 1));\n    }\n\n    println!(\"Starting heavy work at depth {}...wait.\", args.flag_depth);\n    join_recursively(args.flag_depth);\n    println!(\"Heavy work done; check top. You should see CPU usage drop to zero soon.\");\n    println!(\"Press <enter> to quit...\");\n}\n\nfn tasks_ended(args: &Args) {\n    task(args);\n    wait_for_user();\n}\n\nfn task_stall_root(args: &Args) {\n    rayon::join(|| task(args), wait_for_user);\n}\n\nfn task_stall_scope(args: &Args) {\n    rayon::scope(|scope| {\n        scope.spawn(move |_| task(args));\n        scope.spawn(move |_| wait_for_user());\n    });\n}\n"
  },
  {
    "path": "rayon-demo/src/cpu_time/mod.rs",
    "content": "use std::time::{Duration, Instant};\n\n#[cfg(windows)]\nmod win;\n#[cfg(windows)]\npub use self::win::get_cpu_time;\n\n#[cfg(unix)]\nmod unix;\n#[cfg(unix)]\npub use self::unix::get_cpu_time;\n\n#[cfg(not(any(unix, windows)))]\npub fn get_cpu_time() -> Option<u64> {\n    None\n}\n\npub fn get_cpu_duration(start: Option<u64>, stop: Option<u64>) -> Option<Duration> {\n    Some(Duration::from_nanos(stop? - start?))\n}\n\n#[derive(Copy, Clone)]\npub struct CpuMeasure {\n    /// Real time elapsed\n    pub time_duration: Duration,\n\n    /// percentage (0-100) of that as cpu time\n    pub cpu_usage_percent: Option<f64>,\n}\n\npub fn measure_cpu(op: impl FnOnce()) -> CpuMeasure {\n    let time_start = Instant::now();\n    let cpu_start = get_cpu_time();\n\n    op();\n\n    let cpu_stop = get_cpu_time();\n    let time_duration = time_start.elapsed();\n\n    CpuMeasure {\n        time_duration,\n        cpu_usage_percent: get_cpu_duration(cpu_start, cpu_stop)\n            .map(|cpu| 100.0 * cpu.as_secs_f64() / time_duration.as_secs_f64()),\n    }\n}\n\npub fn print_time(m: CpuMeasure) {\n    println!(\"    wallclock: {} ns\", m.time_duration.as_nanos());\n    if let Some(cpu_usage) = m.cpu_usage_percent {\n        println!(\"    cpu usage: {cpu_usage:3.1}%\");\n    } else {\n        println!(\"    cpu usage: N/A\");\n    }\n}\n"
  },
  {
    "path": "rayon-demo/src/cpu_time/unix.rs",
    "content": "use libc::{getrusage, RUSAGE_SELF};\nuse std::mem::MaybeUninit;\n\npub fn get_cpu_time() -> Option<u64> {\n    let usage = unsafe {\n        let mut usage = MaybeUninit::uninit();\n        if getrusage(RUSAGE_SELF, usage.as_mut_ptr()) != 0 {\n            return None;\n        }\n        usage.assume_init()\n    };\n    let user =\n        1_000_000_000 * (usage.ru_utime.tv_sec as u64) + 1_000 * (usage.ru_utime.tv_usec as u64);\n    let system =\n        1_000_000_000 * (usage.ru_stime.tv_sec as u64) + 1_000 * (usage.ru_stime.tv_usec as u64);\n    Some(user + system)\n}\n"
  },
  {
    "path": "rayon-demo/src/cpu_time/win.rs",
    "content": "use std::mem::MaybeUninit;\nuse winapi::um::processthreadsapi::{GetCurrentProcess, GetProcessTimes};\n\npub fn get_cpu_time() -> Option<u64> {\n    let (kernel, user) = unsafe {\n        let process = GetCurrentProcess();\n        let mut _creation = MaybeUninit::uninit();\n        let mut _exit = MaybeUninit::uninit();\n        let mut kernel = MaybeUninit::uninit();\n        let mut user = MaybeUninit::uninit();\n        if GetProcessTimes(\n            process,\n            _creation.as_mut_ptr(),\n            _exit.as_mut_ptr(),\n            kernel.as_mut_ptr(),\n            user.as_mut_ptr(),\n        ) == 0\n        {\n            return None;\n        }\n        (kernel.assume_init(), user.assume_init())\n    };\n    let kernel = (kernel.dwHighDateTime as u64) << 32 | kernel.dwLowDateTime as u64;\n    let user = (user.dwHighDateTime as u64) << 32 | user.dwLowDateTime as u64;\n    Some(100 * (kernel + user))\n}\n"
  },
  {
    "path": "rayon-demo/src/factorial/mod.rs",
    "content": "//! Benchmark Factorial N! = 1×2×⋯×N\n\nuse num::{BigUint, One};\nuse rayon::prelude::*;\nuse std::ops::Mul;\n\nconst N: u32 = 9999;\n\n/// Compute the Factorial using a plain iterator.\nfn factorial(n: u32) -> BigUint {\n    (1..=n).map(BigUint::from).fold(BigUint::one(), Mul::mul)\n}\n\n#[bench]\n/// Benchmark the Factorial using a plain iterator.\nfn factorial_iterator(b: &mut test::Bencher) {\n    let f = factorial(N);\n    b.iter(|| assert_eq!(factorial(test::black_box(N)), f));\n}\n\n#[bench]\n/// Compute the Factorial using rayon::par_iter.\nfn factorial_par_iter(b: &mut test::Bencher) {\n    fn fact(n: u32) -> BigUint {\n        (1..n + 1)\n            .into_par_iter()\n            .map(BigUint::from)\n            .reduce_with(Mul::mul)\n            .unwrap()\n    }\n\n    let f = factorial(N);\n    b.iter(|| assert_eq!(fact(test::black_box(N)), f));\n}\n\n#[bench]\n/// Compute the Factorial using rayon::fold_with.\nfn factorial_fold_with(b: &mut test::Bencher) {\n    fn fact(n: u32) -> BigUint {\n        (1..n + 1)\n            .into_par_iter()\n            .with_min_len(64) // for fair comparison with factorial_fold_chunks_with()\n            .fold_with(BigUint::from(1_u32), |acc, x| acc.mul(x))\n            .reduce_with(Mul::mul)\n            .unwrap()\n    }\n\n    let f = factorial(N);\n    b.iter(|| assert_eq!(fact(test::black_box(N)), f));\n}\n\n#[bench]\n/// Compute the Factorial using rayon::fold_chunks_with.\nfn factorial_fold_chunks_with(b: &mut test::Bencher) {\n    fn fact(n: u32) -> BigUint {\n        (1..n + 1)\n            .into_par_iter()\n            .fold_chunks_with(64, BigUint::from(1_u32), |acc, x| acc.mul(x))\n            .reduce_with(Mul::mul)\n            .unwrap()\n    }\n\n    let f = factorial(N);\n    b.iter(|| assert_eq!(fact(test::black_box(N)), f));\n}\n\n#[bench]\n/// Compute the Factorial using divide-and-conquer serial recursion.\nfn factorial_recursion(b: &mut test::Bencher) {\n    fn product(a: u32, b: u32) -> BigUint {\n        if a == b {\n            return a.into();\n        }\n        let mid = (a + b) / 2;\n        product(a, mid) * product(mid + 1, b)\n    }\n\n    let f = factorial(N);\n    b.iter(|| assert_eq!(product(1, test::black_box(N)), f));\n}\n\n#[bench]\n/// Compute the Factorial using divide-and-conquer parallel join.\nfn factorial_join(b: &mut test::Bencher) {\n    fn product(a: u32, b: u32) -> BigUint {\n        if a == b {\n            return a.into();\n        }\n        let mid = (a + b) / 2;\n        let (x, y) = rayon::join(|| product(a, mid), || product(mid + 1, b));\n        x * y\n    }\n\n    let f = factorial(N);\n    b.iter(|| assert_eq!(product(1, test::black_box(N)), f));\n}\n"
  },
  {
    "path": "rayon-demo/src/fibonacci/mod.rs",
    "content": "//! Benchmark Fibonacci numbers, F(n) = F(n-1) + F(n-2)\n//!\n//! Recursion is a horrible way to compute this -- roughly O(2ⁿ).\n//!\n//! It's potentially interesting for rayon::join, because the splits are\n//! unequal.  F(n-1) has roughly twice as much work to do as F(n-2).  The\n//! imbalance might make it more likely to leave idle threads ready to steal\n//! jobs.  We can also see if there's any effect to having the larger job first\n//! or second.\n//!\n//! We're doing very little real work in each job, so the rayon overhead is\n//! going to dominate.  The serial recursive version will likely be faster,\n//! unless you have a whole lot of CPUs.  The iterative version reveals the\n//! joke.\n\nconst N: u32 = 32;\nconst FN: u32 = 2_178_309;\n\nfn fib_iterative(n: u32) -> u32 {\n    let mut a = 0;\n    let mut b = 1;\n    for _ in 0..n {\n        let c = a + b;\n        a = b;\n        b = c;\n    }\n    a\n}\n\nfn fib_recursive(n: u32) -> u32 {\n    if n < 2 {\n        return n;\n    }\n\n    fib_recursive(n - 1) + fib_recursive(n - 2)\n}\n\n#[bench]\n/// Compute the Fibonacci number recursively, without any parallelism.\nfn fibonacci_recursive(b: &mut test::Bencher) {\n    b.iter(|| assert_eq!(fib_recursive(test::black_box(N)), FN));\n}\n\n#[bench]\n/// Compute the Fibonacci number recursively, using rayon::join.\n/// The larger branch F(N-1) is computed first.\nfn fibonacci_join_1_2(b: &mut test::Bencher) {\n    fn fib(n: u32) -> u32 {\n        if n < 2 {\n            return n;\n        }\n\n        let (a, b) = rayon::join(|| fib(n - 1), || fib(n - 2));\n        a + b\n    }\n\n    b.iter(|| assert_eq!(fib(test::black_box(N)), FN));\n}\n\n#[bench]\n/// Compute the Fibonacci number recursively, using rayon::join.\n/// The smaller branch F(N-2) is computed first.\nfn fibonacci_join_2_1(b: &mut test::Bencher) {\n    fn fib(n: u32) -> u32 {\n        if n < 2 {\n            return n;\n        }\n\n        let (a, b) = rayon::join(|| fib(n - 2), || fib(n - 1));\n        a + b\n    }\n\n    b.iter(|| assert_eq!(fib(test::black_box(N)), FN));\n}\n\n#[bench]\n/// Compute the Fibonacci number recursively, using rayon::iter::split to parallelize.\nfn fibonacci_split_recursive(b: &mut test::Bencher) {\n    fn fib(n: u32) -> u32 {\n        use rayon::iter::ParallelIterator;\n\n        rayon::iter::split(n, |n| {\n            if n < 2 {\n                (n, None)\n            } else {\n                (n - 2, Some(n - 1))\n            }\n        })\n        .map(fib_recursive)\n        .sum()\n    }\n\n    b.iter(|| assert_eq!(fib(test::black_box(N)), FN));\n}\n\n#[bench]\n/// Compute the Fibonacci number iteratively, using rayon::iter::split to parallelize.\nfn fibonacci_split_iterative(b: &mut test::Bencher) {\n    fn fib(n: u32) -> u32 {\n        use rayon::iter::ParallelIterator;\n\n        rayon::iter::split(n, |n| {\n            if n < 2 {\n                (n, None)\n            } else {\n                (n - 2, Some(n - 1))\n            }\n        })\n        .map(fib_iterative)\n        .sum()\n    }\n\n    b.iter(|| assert_eq!(fib(test::black_box(N)), FN));\n}\n\n#[bench]\n/// Compute the Fibonacci number iteratively, just to show how silly the others\n/// are. Parallelism can't make up for a bad choice of algorithm.\nfn fibonacci_iterative(b: &mut test::Bencher) {\n    b.iter(|| assert_eq!(fib_iterative(test::black_box(N)), FN));\n}\n"
  },
  {
    "path": "rayon-demo/src/find/mod.rs",
    "content": "//! Simple benchmarks of `find_any()` and `find_first` performance\n\nmacro_rules! make_tests {\n    ($n:expr, $m:ident) => {\n        mod $m {\n            use rand::distr::StandardUniform;\n            use rand::Rng;\n            use rayon::prelude::*;\n            use std::sync::LazyLock;\n            use test::Bencher;\n\n            static HAYSTACK: LazyLock<Box<[[u32; $n]]>> = LazyLock::new(|| {\n                let rng = crate::seeded_rng();\n                rng.sample_iter(&StandardUniform)\n                    .map(|x| {\n                        let mut result: [u32; $n] = [0; $n];\n                        result[0] = x;\n                        result\n                    })\n                    .take(10_000_000)\n                    .collect()\n            });\n\n            // this is a very dumb find_first algorithm.\n            // no early aborts so we have a linear best case cost.\n            fn find_dumb<I: ParallelIterator, P: Fn(&I::Item) -> bool + Send + Sync>(\n                iter: I,\n                cond: P,\n            ) -> Option<I::Item> {\n                iter.map(|e| if cond(&e) { Some(e) } else { None })\n                    .reduce(|| None, |left, right| left.or(right))\n            }\n\n            #[bench]\n            fn parallel_find_any_start(b: &mut Bencher) {\n                let needle = HAYSTACK[0][0];\n                b.iter(|| assert!(HAYSTACK.par_iter().find_any(|&&x| x[0] == needle).is_some()));\n            }\n\n            #[bench]\n            fn parallel_find_first_start(b: &mut Bencher) {\n                let needle = HAYSTACK[0][0];\n                b.iter(|| assert!(HAYSTACK.par_iter().find_any(|&&x| x[0] == needle).is_some()));\n            }\n\n            #[bench]\n            fn parallel_find_first_blocks_start(b: &mut Bencher) {\n                let needle = HAYSTACK[0][0];\n                b.iter(|| {\n                    assert!(HAYSTACK\n                        .par_iter()\n                        .by_exponential_blocks()\n                        .find_first(|&&x| x[0] == needle)\n                        .is_some())\n                });\n            }\n\n            #[bench]\n            fn serial_find_start(b: &mut Bencher) {\n                let needle = HAYSTACK[0][0];\n                b.iter(|| assert!(HAYSTACK.iter().find(|&&x| x[0] == needle).is_some()));\n            }\n\n            #[bench]\n            fn parallel_find_any_end(b: &mut Bencher) {\n                let needle = HAYSTACK[HAYSTACK.len() - 1][0];\n                b.iter(|| assert!(HAYSTACK.par_iter().find_any(|&&x| x[0] == needle).is_some()));\n            }\n            #[bench]\n            fn parallel_find_first_end(b: &mut Bencher) {\n                let needle = HAYSTACK[HAYSTACK.len() - 1][0];\n                b.iter(|| {\n                    assert!(HAYSTACK\n                        .par_iter()\n                        .find_first(|&&x| x[0] == needle)\n                        .is_some())\n                });\n            }\n            #[bench]\n            fn parallel_find_first_blocks_end(b: &mut Bencher) {\n                let needle = HAYSTACK[HAYSTACK.len() - 1][0];\n                b.iter(|| {\n                    assert!(HAYSTACK\n                        .par_iter()\n                        .by_exponential_blocks()\n                        .find_first(|&&x| x[0] == needle)\n                        .is_some())\n                });\n            }\n\n            #[bench]\n            fn serial_find_end(b: &mut Bencher) {\n                let needle = HAYSTACK[HAYSTACK.len() - 1][0];\n                b.iter(|| assert!(HAYSTACK.iter().find(|&&x| x[0] == needle).is_some()));\n            }\n\n            #[bench]\n            fn parallel_find_any_third(b: &mut Bencher) {\n                let needle = HAYSTACK[HAYSTACK.len() / 3][0];\n                b.iter(|| assert!(HAYSTACK.par_iter().find_any(|&&x| x[0] == needle).is_some()));\n            }\n\n            #[bench]\n            fn parallel_find_first_third(b: &mut Bencher) {\n                let needle = HAYSTACK[HAYSTACK.len() / 3][0];\n                b.iter(|| {\n                    assert!(HAYSTACK\n                        .par_iter()\n                        .find_first(|&&x| x[0] == needle)\n                        .is_some())\n                });\n            }\n\n            #[bench]\n            fn parallel_find_dumb_third(b: &mut Bencher) {\n                let needle = HAYSTACK[HAYSTACK.len() / 3][0];\n                b.iter(\n                    || assert!(find_dumb(HAYSTACK.par_iter(), (|&&x| x[0] == needle)).is_some()),\n                );\n            }\n\n            #[bench]\n            fn parallel_find_first_blocks_third(b: &mut Bencher) {\n                let needle = HAYSTACK[HAYSTACK.len() / 3][0];\n                b.iter(|| {\n                    assert!(HAYSTACK\n                        .par_iter()\n                        .by_exponential_blocks()\n                        .find_first(|&&x| x[0] == needle)\n                        .is_some())\n                });\n            }\n\n            #[bench]\n            fn serial_find_third(b: &mut Bencher) {\n                let needle = HAYSTACK[HAYSTACK.len() / 3][0];\n                b.iter(|| assert!(HAYSTACK.iter().find(|&&x| x[0] == needle).is_some()));\n            }\n\n            #[bench]\n            fn parallel_find_any_middle(b: &mut Bencher) {\n                let needle = HAYSTACK[(HAYSTACK.len() / 2).saturating_sub(1)][0];\n                b.iter(|| assert!(HAYSTACK.par_iter().find_any(|&&x| x[0] == needle).is_some()));\n            }\n\n            #[bench]\n            fn parallel_find_first_middle(b: &mut Bencher) {\n                let needle = HAYSTACK[(HAYSTACK.len() / 2).saturating_sub(1)][0];\n                b.iter(|| {\n                    assert!(HAYSTACK\n                        .par_iter()\n                        .find_first(|&&x| x[0] == needle)\n                        .is_some())\n                });\n            }\n\n            #[bench]\n            fn parallel_find_dumb_middle(b: &mut Bencher) {\n                let needle = HAYSTACK[(HAYSTACK.len() / 2).saturating_sub(1)][0];\n                b.iter(\n                    || assert!(find_dumb(HAYSTACK.par_iter(), (|&&x| x[0] == needle)).is_some()),\n                );\n            }\n\n            #[bench]\n            fn parallel_find_first_blocks_middle(b: &mut Bencher) {\n                let needle = HAYSTACK[(HAYSTACK.len() / 2).saturating_sub(1)][0];\n                b.iter(|| {\n                    assert!(HAYSTACK\n                        .par_iter()\n                        .by_exponential_blocks()\n                        .find_first(|&&x| x[0] == needle)\n                        .is_some())\n                });\n            }\n\n            #[bench]\n            fn serial_find_middle(b: &mut Bencher) {\n                let needle = HAYSTACK[(HAYSTACK.len() / 2).saturating_sub(1)][0];\n                b.iter(|| assert!(HAYSTACK.iter().find(|&&x| x[0] == needle).is_some()));\n            }\n\n            #[bench]\n            fn parallel_find_any_two_thirds(b: &mut Bencher) {\n                let needle = HAYSTACK[HAYSTACK.len() / 3 * 2][0];\n                b.iter(|| assert!(HAYSTACK.par_iter().find_any(|&&x| x[0] == needle).is_some()));\n            }\n\n            #[bench]\n            fn parallel_find_first_two_thirds(b: &mut Bencher) {\n                let needle = HAYSTACK[HAYSTACK.len() / 3 * 2][0];\n                b.iter(|| {\n                    assert!(HAYSTACK\n                        .par_iter()\n                        .find_first(|&&x| x[0] == needle)\n                        .is_some())\n                });\n            }\n\n            #[bench]\n            fn parallel_find_first_blocks_two_thirds(b: &mut Bencher) {\n                let needle = HAYSTACK[HAYSTACK.len() / 3 * 2][0];\n                b.iter(|| {\n                    assert!(HAYSTACK\n                        .par_iter()\n                        .by_exponential_blocks()\n                        .find_first(|&&x| x[0] == needle)\n                        .is_some())\n                });\n            }\n\n            #[bench]\n            fn serial_find_two_thirds(b: &mut Bencher) {\n                let needle = HAYSTACK[HAYSTACK.len() / 3 * 2][0];\n                b.iter(|| assert!(HAYSTACK.iter().find(|&&x| x[0] == needle).is_some()));\n            }\n\n            #[bench]\n            fn parallel_find_any_missing(b: &mut Bencher) {\n                let needle = HAYSTACK.iter().map(|v| v[0]).max().unwrap() + 1;\n                b.iter(|| assert!(HAYSTACK.par_iter().find_any(|&&x| x[0] == needle).is_none()));\n            }\n\n            #[bench]\n            fn parallel_find_first_missing(b: &mut Bencher) {\n                let needle = HAYSTACK.iter().map(|v| v[0]).max().unwrap() + 1;\n                b.iter(|| {\n                    assert!(HAYSTACK\n                        .par_iter()\n                        .find_first(|&&x| x[0] == needle)\n                        .is_none())\n                });\n            }\n\n            #[bench]\n            fn parallel_find_first_blocks_missing(b: &mut Bencher) {\n                let needle = HAYSTACK.iter().map(|v| v[0]).max().unwrap() + 1;\n                b.iter(|| {\n                    assert!(HAYSTACK\n                        .par_iter()\n                        .by_exponential_blocks()\n                        .find_first(|&&x| x[0] == needle)\n                        .is_none())\n                });\n            }\n\n            #[bench]\n            fn serial_find_missing(b: &mut Bencher) {\n                let needle = HAYSTACK.iter().map(|v| v[0]).max().unwrap() + 1;\n                b.iter(|| assert!(HAYSTACK.iter().find(|&&x| x[0] == needle).is_none()));\n            }\n\n            #[bench]\n            fn parallel_find_any_common(b: &mut Bencher) {\n                b.iter(|| {\n                    assert!(HAYSTACK\n                        .par_iter()\n                        .find_any(|&&x| x[0] % 1000 == 999)\n                        .is_some())\n                });\n            }\n\n            #[bench]\n            fn serial_find_common(b: &mut Bencher) {\n                b.iter(|| assert!(HAYSTACK.iter().find(|&&x| x[0] % 1000 == 999).is_some()));\n            }\n        }\n    };\n}\n\nmake_tests!(1, size1);\n// make_tests!(64, size64);\n// make_tests!(256, size256);\n"
  },
  {
    "path": "rayon-demo/src/join_microbench.rs",
    "content": "//! Some microbenchmarks that stress test a pure `join` path.\n\nuse rayon::prelude::*;\nuse test::Bencher;\n\n#[bench]\nfn increment_all(b: &mut Bencher) {\n    let mut big_vec = vec![0_usize; 100 * 1024];\n    b.iter(|| {\n        big_vec.par_iter_mut().for_each(|p| *p = p.wrapping_add(1));\n    });\n}\n\n#[bench]\nfn increment_all_min(b: &mut Bencher) {\n    let mut big_vec = vec![0_usize; 100 * 1024];\n    b.iter(|| {\n        big_vec\n            .par_iter_mut()\n            .with_min_len(1024)\n            .for_each(|p| *p = p.wrapping_add(1));\n    });\n}\n\n#[bench]\nfn increment_all_serialized(b: &mut Bencher) {\n    let mut big_vec = vec![0_usize; 100 * 1024];\n    b.iter(|| {\n        big_vec\n            .par_iter_mut()\n            .with_min_len(usize::MAX)\n            .for_each(|p| *p = p.wrapping_add(1));\n    });\n}\n\n#[bench]\nfn increment_all_max(b: &mut Bencher) {\n    let mut big_vec = vec![0_usize; 100 * 1024];\n    b.iter(|| {\n        big_vec\n            .par_iter_mut()\n            .with_max_len(100)\n            .for_each(|p| *p = p.wrapping_add(1));\n    });\n}\n\n#[bench]\nfn increment_all_atomized(b: &mut Bencher) {\n    let mut big_vec = vec![0_usize; 100 * 1024];\n    b.iter(|| {\n        big_vec\n            .par_iter_mut()\n            .with_max_len(1)\n            .for_each(|p| *p = p.wrapping_add(1));\n    });\n}\n\n#[bench]\nfn join_recursively(b: &mut Bencher) {\n    fn join_recursively(n: usize) {\n        if n == 0 {\n            return;\n        }\n        rayon::join(|| join_recursively(n - 1), || join_recursively(n - 1));\n    }\n\n    b.iter(|| {\n        join_recursively(16);\n    });\n}\n"
  },
  {
    "path": "rayon-demo/src/lib.rs",
    "content": "// Make sure the examples in the main README actually compile.\n#[cfg(doctest)]\ndoc_comment::doctest!(\"../../README.md\");\n"
  },
  {
    "path": "rayon-demo/src/life/bench.rs",
    "content": "use super::Board;\n\n#[bench]\nfn generations(b: &mut ::test::Bencher) {\n    b.iter(|| super::generations(Board::new(200, 200).random(), 100));\n}\n\n#[bench]\nfn par_iter_generations(b: &mut ::test::Bencher) {\n    b.iter(|| super::parallel_generations(Board::new(200, 200).random(), 100));\n}\n\n#[bench]\nfn par_bridge_generations(b: &mut ::test::Bencher) {\n    b.iter(|| super::par_bridge_generations(Board::new(200, 200).random(), 100));\n}\n"
  },
  {
    "path": "rayon-demo/src/life/mod.rs",
    "content": "const USAGE: &str = \"\nUsage: life bench [--size N] [--gens N] [--skip-bridge]\n       life play [--size N] [--gens N] [--fps N] [--skip-bridge]\n       life --help\nConway's Game of Life.\n\nCommands:\n    bench           Run the benchmark in different modes and print the timings.\n    play            Run with a max frame rate and monitor CPU resources.\nOptions:\n    --size N        Size of the game board (N x N) [default: 200]\n    --gens N        Simulate N generations [default: 100]\n    --fps N         Maximum frame rate [default: 60]\n    --skip-bridge   Skips the tests with par-bridge, as it is much slower.\n    -h, --help      Show this message.\n\";\n\nuse crate::cpu_time::{self, CpuMeasure};\nuse rand::distr::StandardUniform;\nuse rand::{rng, Rng};\nuse std::iter::repeat;\nuse std::sync::Arc;\nuse std::thread;\nuse std::time::{Duration, Instant};\n\nuse docopt::Docopt;\nuse rayon::prelude::*;\n\n#[cfg(test)]\nmod bench;\n\n#[derive(serde::Deserialize)]\npub struct Args {\n    cmd_bench: bool,\n    cmd_play: bool,\n    flag_size: usize,\n    flag_gens: usize,\n    flag_fps: usize,\n    flag_skip_bridge: bool,\n}\n\n#[derive(PartialEq, Eq, Clone, Debug)]\npub struct Board {\n    board: Vec<bool>,\n    survive: Arc<Vec<usize>>,\n    born: Arc<Vec<usize>>,\n    rows: usize,\n    cols: usize,\n}\n\nimpl Board {\n    pub fn new(rows: usize, cols: usize) -> Board {\n        let born = vec![3];\n        let survive = vec![2, 3];\n\n        Board::new_with_custom_rules(rows, cols, born, survive)\n    }\n\n    fn new_with_custom_rules(\n        rows: usize,\n        cols: usize,\n        born: Vec<usize>,\n        survive: Vec<usize>,\n    ) -> Board {\n        let new_board = repeat(false).take(rows * cols).collect();\n\n        Board {\n            board: new_board,\n            born: Arc::new(born),\n            survive: Arc::new(survive),\n            rows,\n            cols,\n        }\n    }\n\n    fn len(&self) -> usize {\n        self.rows * self.cols\n    }\n\n    fn next_board(&self, new_board: Vec<bool>) -> Board {\n        assert!(new_board.len() == self.len());\n\n        Board {\n            board: new_board,\n            born: self.born.clone(),\n            survive: self.survive.clone(),\n            rows: self.rows,\n            cols: self.cols,\n        }\n    }\n\n    pub fn random(&self) -> Board {\n        let new_brd = rng()\n            .sample_iter(&StandardUniform)\n            .take(self.len())\n            .collect();\n\n        self.next_board(new_brd)\n    }\n\n    pub fn next_generation(&self) -> Board {\n        let new_brd = (0..self.len())\n            .map(|cell| self.successor_cell(cell))\n            .collect();\n\n        self.next_board(new_brd)\n    }\n\n    pub fn parallel_next_generation(&self) -> Board {\n        let new_brd = (0..self.len())\n            .into_par_iter()\n            .map(|cell| self.successor_cell(cell))\n            .collect();\n\n        self.next_board(new_brd)\n    }\n\n    pub fn par_bridge_next_generation(&self) -> Board {\n        let new_brd = (0..self.len())\n            .par_bridge()\n            .map(|cell| self.successor_cell(cell))\n            .collect();\n\n        self.next_board(new_brd)\n    }\n\n    fn cell_live(&self, x: usize, y: usize) -> bool {\n        !(x >= self.cols || y >= self.rows) && self.board[y * self.cols + x]\n    }\n\n    fn living_neighbors(&self, x: usize, y: usize) -> usize {\n        let x_1 = x.wrapping_sub(1);\n        let y_1 = y.wrapping_sub(1);\n        let neighbors = [\n            self.cell_live(x_1, y_1),\n            self.cell_live(x, y_1),\n            self.cell_live(x + 1, y_1),\n            self.cell_live(x_1, y),\n            self.cell_live(x + 1, y),\n            self.cell_live(x_1, y + 1),\n            self.cell_live(x, y + 1),\n            self.cell_live(x + 1, y + 1),\n        ];\n        neighbors.iter().filter(|&x| *x).count()\n    }\n\n    fn successor_cell(&self, cell: usize) -> bool {\n        self.successor(cell % self.cols, cell / self.cols)\n    }\n\n    fn successor(&self, x: usize, y: usize) -> bool {\n        let neighbors = self.living_neighbors(x, y);\n        if self.cell_live(x, y) {\n            self.survive.contains(&neighbors)\n        } else {\n            self.born.contains(&neighbors)\n        }\n    }\n}\n\n#[test]\nfn test_life() {\n    let mut brd1 = Board::new(200, 200).random();\n    let mut brd2 = brd1.clone();\n\n    for _ in 0..100 {\n        brd1 = brd1.next_generation();\n        brd2 = brd2.parallel_next_generation();\n\n        assert_eq!(brd1, brd2);\n    }\n}\n\nfn generations(board: Board, gens: usize) {\n    let mut brd = board;\n    for _ in 0..gens {\n        brd = brd.next_generation();\n    }\n}\n\nfn parallel_generations(board: Board, gens: usize) {\n    let mut brd = board;\n    for _ in 0..gens {\n        brd = brd.parallel_next_generation();\n    }\n}\n\nfn par_bridge_generations(board: Board, gens: usize) {\n    let mut brd = board;\n    for _ in 0..gens {\n        brd = brd.par_bridge_next_generation();\n    }\n}\n\nfn delay(last_start: Instant, min_interval: Duration) -> Instant {\n    let mut current_time = Instant::now();\n    let elapsed = current_time - last_start;\n    if elapsed < min_interval {\n        let delay = min_interval - elapsed;\n        thread::sleep(delay);\n        current_time += delay;\n    }\n    current_time\n}\n\nfn generations_limited(board: Board, gens: usize, min_interval: Duration) {\n    let mut brd = board;\n    let mut time = Instant::now();\n    for _ in 0..gens {\n        brd = brd.next_generation();\n        time = delay(time, min_interval);\n    }\n}\n\nfn parallel_generations_limited(board: Board, gens: usize, min_interval: Duration) {\n    let mut brd = board;\n    let mut time = Instant::now();\n    for _ in 0..gens {\n        brd = brd.parallel_next_generation();\n        time = delay(time, min_interval);\n    }\n}\n\nfn par_bridge_generations_limited(board: Board, gens: usize, min_interval: Duration) {\n    let mut brd = board;\n    let mut time = Instant::now();\n    for _ in 0..gens {\n        brd = brd.par_bridge_next_generation();\n        time = delay(time, min_interval);\n    }\n}\n\nfn measure(f: fn(Board, usize) -> (), args: &Args) -> Duration {\n    let (n, gens) = (args.flag_size, args.flag_gens);\n    let brd = Board::new(n, n).random();\n    let start = Instant::now();\n\n    f(brd, gens);\n\n    start.elapsed()\n}\n\nstruct CpuResult {\n    actual_fps: f64,\n    cpu_usage_percent: Option<f64>,\n}\n\nfn measure_cpu(f: fn(Board, usize, Duration) -> (), args: &Args) -> CpuResult {\n    let (n, gens, rate) = (args.flag_size, args.flag_gens, args.flag_fps);\n    let interval = Duration::from_secs_f64(1.0 / rate as f64);\n    let brd = Board::new(n, n).random();\n\n    let CpuMeasure {\n        time_duration,\n        cpu_usage_percent,\n    } = cpu_time::measure_cpu(|| f(brd, gens, interval));\n\n    CpuResult {\n        actual_fps: gens as f64 / time_duration.as_secs_f64(),\n        cpu_usage_percent,\n    }\n}\n\npub fn main(args: &[String]) {\n    let args: Args = Docopt::new(USAGE)\n        .and_then(|d| d.argv(args).deserialize())\n        .unwrap_or_else(|e| e.exit());\n\n    if args.cmd_bench {\n        let serial = measure(generations, &args).as_nanos();\n        println!(\"  serial: {serial:10} ns\");\n\n        let parallel = measure(parallel_generations, &args).as_nanos();\n        println!(\n            \"parallel: {:10} ns -> {:.2}x speedup\",\n            parallel,\n            serial as f64 / parallel as f64\n        );\n\n        if !args.flag_skip_bridge {\n            let par_bridge = measure(par_bridge_generations, &args).as_nanos();\n            println!(\n                \"par_bridge: {:10} ns -> {:.2}x speedup\",\n                par_bridge,\n                serial as f64 / par_bridge as f64\n            );\n        }\n    }\n\n    if args.cmd_play {\n        let serial = measure_cpu(generations_limited, &args);\n        println!(\"  serial: {:.2} fps\", serial.actual_fps);\n        if let Some(cpu_usage) = serial.cpu_usage_percent {\n            println!(\"    cpu usage: {cpu_usage:.1}%\");\n        }\n\n        let parallel = measure_cpu(parallel_generations_limited, &args);\n        println!(\"parallel: {:.2} fps\", parallel.actual_fps);\n        if let Some(cpu_usage) = parallel.cpu_usage_percent {\n            println!(\"  cpu usage: {cpu_usage:.1}%\");\n        }\n\n        if !args.flag_skip_bridge {\n            let par_bridge = measure_cpu(par_bridge_generations_limited, &args);\n            println!(\"par_bridge: {:.2} fps\", par_bridge.actual_fps);\n            if let Some(cpu_usage) = par_bridge.cpu_usage_percent {\n                println!(\"  cpu usage: {cpu_usage:.1}%\");\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "rayon-demo/src/main.rs",
    "content": "#![cfg_attr(test, feature(test))]\n#![warn(rust_2018_idioms)]\n\nuse std::{env, io, io::prelude::*, process::exit};\n\nmod cpu_time;\nmod life;\nmod matmul;\nmod mergesort;\nmod nbody;\nmod noop;\nmod quicksort;\nmod sieve;\nmod tsp;\n\n// these are not \"full-fledged\" benchmarks yet,\n// they only run with cargo bench\n#[cfg(test)]\nmod factorial;\n#[cfg(test)]\nmod fibonacci;\n#[cfg(test)]\nmod find;\n#[cfg(test)]\nmod join_microbench;\n#[cfg(test)]\nmod map_collect;\n#[cfg(test)]\nmod pythagoras;\n#[cfg(test)]\nmod sort;\n#[cfg(test)]\nmod str_split;\n#[cfg(test)]\nmod tree;\n#[cfg(test)]\nmod vec_collect;\n\n#[cfg(test)]\nextern crate test;\n\nconst USAGE: &str = \"\nUsage: rayon-demo bench\n       rayon-demo <demo-name> [ options ]\n       rayon-demo --help\n\nA collection of different benchmarks of Rayon. You can run the full\nbenchmark suite by executing `cargo bench` or `rayon-demo bench`.\n\nAlternatively, you can run individual benchmarks by running\n`rayon-demo foo`, where `foo` is the name of a benchmark. Each\nbenchmark has its own options and modes, so try `rayon-demo foo\n--help`.\n\nBenchmarks:\n\n  - life : Conway's Game of Life.\n  - nbody: A physics simulation of multiple bodies attracting and repelling\n           one another.\n  - sieve: Finding primes using a Sieve of Eratosthenes.\n  - matmul: Parallel matrix multiplication.\n  - mergesort: Parallel mergesort.\n  - noop: Launch empty tasks to measure CPU usage.\n  - quicksort: Parallel quicksort.\n  - tsp: Traveling salesman problem solver (sample data sets in `data/tsp`).\n\";\n\nfn usage() -> ! {\n    let _ = writeln!(&mut io::stderr(), \"{USAGE}\");\n    exit(1);\n}\n\nfn main() {\n    let args: Vec<String> = env::args().collect();\n\n    if args.len() < 2 {\n        usage();\n    }\n\n    let bench_name = &args[1];\n    match &bench_name[..] {\n        \"matmul\" => matmul::main(&args[1..]),\n        \"mergesort\" => mergesort::main(&args[1..]),\n        \"nbody\" => nbody::main(&args[1..]),\n        \"quicksort\" => quicksort::main(&args[1..]),\n        \"sieve\" => sieve::main(&args[1..]),\n        \"tsp\" => tsp::main(&args[1..]),\n        \"life\" => life::main(&args[1..]),\n        \"noop\" => noop::main(&args[1..]),\n        _ => usage(),\n    }\n}\n\nfn seeded_rng() -> rand_xorshift::XorShiftRng {\n    use rand::SeedableRng;\n    use rand_xorshift::XorShiftRng;\n    let mut seed = <XorShiftRng as SeedableRng>::Seed::default();\n    (0..).zip(seed.as_mut()).for_each(|(i, x)| *x = i);\n    XorShiftRng::from_seed(seed)\n}\n"
  },
  {
    "path": "rayon-demo/src/map_collect.rs",
    "content": "//! Some benchmarks stress-testing various ways to build the standard\n//! `HashMap` data structures from the standard library.\n\nmod util {\n    use rayon::prelude::*;\n    use std::collections::{HashMap, LinkedList};\n    use std::hash::Hash;\n    use std::sync::Mutex;\n\n    /// Do whatever `collect` does by default.\n    pub fn collect<K, V, PI>(pi: PI) -> HashMap<K, V>\n    where\n        K: Send + Hash + Eq,\n        V: Send,\n        PI: ParallelIterator<Item = (K, V)> + Send,\n    {\n        pi.collect()\n    }\n\n    /// Use a system mutex.\n    pub fn mutex<K, V, PI>(pi: PI) -> HashMap<K, V>\n    where\n        K: Send + Hash + Eq,\n        V: Send,\n        PI: ParallelIterator<Item = (K, V)> + Send,\n    {\n        let mutex = Mutex::new(HashMap::new());\n        pi.for_each(|(k, v)| {\n            let mut guard = mutex.lock().unwrap();\n            guard.insert(k, v);\n        });\n        mutex.into_inner().unwrap()\n    }\n\n    /// Use a system mutex over a folded vec.\n    pub fn mutex_vec<K, V, PI>(pi: PI) -> HashMap<K, V>\n    where\n        K: Send + Hash + Eq,\n        V: Send,\n        PI: ParallelIterator<Item = (K, V)> + Send,\n    {\n        let mutex = Mutex::new(HashMap::new());\n        pi.fold(Vec::new, |mut vec, elem| {\n            vec.push(elem);\n            vec\n        })\n        .for_each(|vec| {\n            let mut guard = mutex.lock().unwrap();\n            guard.extend(vec);\n        });\n        mutex.into_inner().unwrap()\n    }\n\n    /// Collect a linked list intermediary.\n    pub fn linked_list_collect<K, V, PI>(pi: PI) -> HashMap<K, V>\n    where\n        K: Send + Hash + Eq,\n        V: Send,\n        PI: ParallelIterator<Item = (K, V)> + Send,\n    {\n        let list: LinkedList<(_, _)> = pi.collect();\n        list.into_iter().collect()\n    }\n\n    /// Collect a linked list of vectors intermediary.\n    pub fn linked_list_collect_vec<K, V, PI>(pi: PI) -> HashMap<K, V>\n    where\n        K: Send + Hash + Eq,\n        V: Send,\n        PI: ParallelIterator<Item = (K, V)> + Send,\n    {\n        let list: LinkedList<Vec<(_, _)>> = pi\n            .fold(Vec::new, |mut vec, elem| {\n                vec.push(elem);\n                vec\n            })\n            .collect();\n        list.into_iter().fold(HashMap::new(), |mut map, vec| {\n            map.extend(vec);\n            map\n        })\n    }\n\n    /// Collect a linked list of vectors intermediary, with a size hint.\n    pub fn linked_list_collect_vec_sized<K, V, PI>(pi: PI) -> HashMap<K, V>\n    where\n        K: Send + Hash + Eq,\n        V: Send,\n        PI: ParallelIterator<Item = (K, V)> + Send,\n    {\n        let list: LinkedList<Vec<(_, _)>> = pi\n            .fold(Vec::new, |mut vec, elem| {\n                vec.push(elem);\n                vec\n            })\n            .collect();\n\n        let len = list.iter().map(Vec::len).sum();\n        list.into_iter()\n            .fold(HashMap::with_capacity(len), |mut map, vec| {\n                map.extend(vec);\n                map\n            })\n    }\n\n    /// Map-Reduce a linked list of vectors intermediary, with a size hint.\n    pub fn linked_list_map_reduce_vec_sized<K, V, PI>(pi: PI) -> HashMap<K, V>\n    where\n        K: Send + Hash + Eq,\n        V: Send,\n        PI: ParallelIterator<Item = (K, V)> + Send,\n    {\n        let list: LinkedList<Vec<(_, _)>> = pi\n            .fold(Vec::new, |mut vec, elem| {\n                vec.push(elem);\n                vec\n            })\n            .map(|vec| {\n                let mut list = LinkedList::new();\n                list.push_back(vec);\n                list\n            })\n            .reduce(LinkedList::new, |mut list1, mut list2| {\n                list1.append(&mut list2);\n                list1\n            });\n\n        let len = list.iter().map(Vec::len).sum();\n        list.into_iter()\n            .fold(HashMap::with_capacity(len), |mut map, vec| {\n                map.extend(vec);\n                map\n            })\n    }\n\n    /// Map-Reduce a vector of vectors intermediary, with a size hint.\n    pub fn vec_vec_sized<K, V, PI>(pi: PI) -> HashMap<K, V>\n    where\n        K: Send + Hash + Eq,\n        V: Send,\n        PI: ParallelIterator<Item = (K, V)> + Send,\n    {\n        let vecs: Vec<Vec<(_, _)>> = pi\n            .fold(Vec::new, |mut vec, elem| {\n                vec.push(elem);\n                vec\n            })\n            .map(|v| vec![v])\n            .reduce(Vec::new, |mut left, mut right| {\n                left.append(&mut right);\n                left\n            });\n\n        let len = vecs.iter().map(Vec::len).sum();\n        vecs.into_iter()\n            .fold(HashMap::with_capacity(len), |mut map, vec| {\n                map.extend(vec);\n                map\n            })\n    }\n\n    /// Fold into hashmaps and then reduce them together.\n    pub fn fold<K, V, PI>(pi: PI) -> HashMap<K, V>\n    where\n        K: Send + Hash + Eq,\n        V: Send,\n        PI: ParallelIterator<Item = (K, V)> + Send,\n    {\n        pi.fold(HashMap::new, |mut map, (k, v)| {\n            map.insert(k, v);\n            map\n        })\n        .reduce(HashMap::new, |mut map1, mut map2| {\n            if map1.len() > map2.len() {\n                map1.extend(map2);\n                map1\n            } else {\n                map2.extend(map1);\n                map2\n            }\n        })\n    }\n\n    /// Fold into vecs and then reduce them together as hashmaps.\n    pub fn fold_vec<K, V, PI>(pi: PI) -> HashMap<K, V>\n    where\n        K: Send + Hash + Eq,\n        V: Send,\n        PI: ParallelIterator<Item = (K, V)> + Send,\n    {\n        pi.fold(Vec::new, |mut vec, elem| {\n            vec.push(elem);\n            vec\n        })\n        .map(HashMap::from_iter)\n        .reduce(HashMap::new, |mut map1, map2| {\n            map1.extend(map2);\n            map1\n        })\n    }\n}\n\nmacro_rules! make_bench {\n    ($generate:ident, $check:ident) => {\n        #[bench]\n        fn with_collect(b: &mut ::test::Bencher) {\n            use crate::map_collect::util;\n            let mut map = None;\n            b.iter(|| map = Some(util::collect($generate())));\n            $check(&map.unwrap());\n        }\n\n        #[bench]\n        fn with_mutex(b: &mut ::test::Bencher) {\n            use crate::map_collect::util;\n            let mut map = None;\n            b.iter(|| map = Some(util::mutex($generate())));\n            $check(&map.unwrap());\n        }\n\n        #[bench]\n        fn with_mutex_vec(b: &mut ::test::Bencher) {\n            use crate::map_collect::util;\n            let mut map = None;\n            b.iter(|| map = Some(util::mutex_vec($generate())));\n            $check(&map.unwrap());\n        }\n\n        #[bench]\n        fn with_linked_list_collect(b: &mut ::test::Bencher) {\n            use crate::map_collect::util;\n            let mut map = None;\n            b.iter(|| map = Some(util::linked_list_collect($generate())));\n            $check(&map.unwrap());\n        }\n\n        #[bench]\n        fn with_linked_list_collect_vec(b: &mut ::test::Bencher) {\n            use crate::map_collect::util;\n            let mut map = None;\n            b.iter(|| map = Some(util::linked_list_collect_vec($generate())));\n            $check(&map.unwrap());\n        }\n\n        #[bench]\n        fn with_linked_list_collect_vec_sized(b: &mut ::test::Bencher) {\n            use crate::map_collect::util;\n            let mut map = None;\n            b.iter(|| map = Some(util::linked_list_collect_vec_sized($generate())));\n            $check(&map.unwrap());\n        }\n\n        #[bench]\n        fn with_linked_list_map_reduce_vec_sized(b: &mut ::test::Bencher) {\n            use crate::map_collect::util;\n            let mut map = None;\n            b.iter(|| map = Some(util::linked_list_map_reduce_vec_sized($generate())));\n            $check(&map.unwrap());\n        }\n\n        #[bench]\n        fn with_vec_vec_sized(b: &mut ::test::Bencher) {\n            use crate::map_collect::util;\n            let mut map = None;\n            b.iter(|| map = Some(util::vec_vec_sized($generate())));\n            $check(&map.unwrap());\n        }\n\n        #[bench]\n        fn with_fold(b: &mut ::test::Bencher) {\n            use crate::map_collect::util;\n            let mut map = None;\n            b.iter(|| map = Some(util::fold($generate())));\n            $check(&map.unwrap());\n        }\n\n        #[bench]\n        fn with_fold_vec(b: &mut ::test::Bencher) {\n            use crate::map_collect::util;\n            let mut map = None;\n            b.iter(|| map = Some(util::fold_vec($generate())));\n            $check(&map.unwrap());\n        }\n    };\n}\n\n/// Tests a big map mapping `i -> i` forall i in 0 to N. This map is\n/// interesting because it has no conflicts, so each parallel\n/// iteration adds a distinct entry into the map.\nmod i_to_i {\n    use rayon::prelude::*;\n    use std::collections::HashMap;\n\n    const N: u32 = 256 * 1024;\n\n    fn generate() -> impl ParallelIterator<Item = (u32, u32)> {\n        (0_u32..N).into_par_iter().map(|i| (i, i))\n    }\n\n    fn check(hm: &HashMap<u32, u32>) {\n        assert_eq!(hm.len(), N as usize);\n        for i in 0..N {\n            assert_eq!(hm[&i], i);\n        }\n    }\n\n    make_bench!(generate, check);\n}\n\n/// Tests a big map mapping `i % 10 -> i` forall i in 0 to N. This map\n/// is interesting because it has lots of conflicts, so parallel\n/// iterations sometimes overwrite entries.\nmod i_mod_10_to_i {\n    use rayon::prelude::*;\n    use std::collections::HashMap;\n\n    const N: u32 = 256 * 1024;\n\n    fn generate() -> impl ParallelIterator<Item = (u32, u32)> {\n        (0_u32..N).into_par_iter().map(|i| (i % 10, i))\n    }\n\n    fn check(hm: &HashMap<u32, u32>) {\n        assert_eq!(hm.len(), 10);\n        for (&k, &v) in hm {\n            assert_eq!(k, v % 10);\n        }\n    }\n\n    make_bench!(generate, check);\n}\n"
  },
  {
    "path": "rayon-demo/src/matmul/bench.rs",
    "content": "const ROW_SIZE: usize = 256;\n\n#[bench]\nfn bench_matmul_strassen(b: &mut test::Bencher) {\n    let n = ROW_SIZE * ROW_SIZE;\n    let x = vec![1f32; n];\n    let y = vec![2f32; n];\n    let mut z = vec![0f32; n];\n\n    b.iter(|| {\n        super::matmul_strassen(&x, &y, &mut z);\n    });\n}\n"
  },
  {
    "path": "rayon-demo/src/matmul/mod.rs",
    "content": "const USAGE: &str = \"\nUsage: matmul bench [--size N]\n       matmul --help\nParallel matrix multiplication.\n\nCommands:\n    bench           Run the benchmark in different modes and print the timings.\nOptions:\n    --size N        Row-size of matrices (rounded up to power of 2) [default: 1024]\n    -h, --help      Show this message.\n\";\n\n#[derive(serde::Deserialize)]\npub struct Args {\n    cmd_bench: bool,\n    flag_size: usize,\n}\n\nuse std::time::Instant;\n\nuse docopt::Docopt;\nuse rayon::prelude::*;\n\n// TODO: Investigate other cache patterns for row-major order that may be more\n// parallelizable.\n// https://tavianator.com/a-quick-trick-for-faster-naive-matrix-multiplication/\npub fn seq_matmul(a: &[f32], b: &[f32], dest: &mut [f32]) {\n    // Zero dest, as it may be uninitialized.\n    for d in dest.iter_mut() {\n        *d = 0.0;\n    }\n    // Multiply in row-major order.\n    // D[i,j] = sum for all k A[i,k] * B[k,j]\n    let bits = dest.len().trailing_zeros() / 2;\n    let n = 1 << bits;\n    for i in 0..n {\n        for j in 0..n {\n            let mut sum = 0.0;\n            for k in 0..n {\n                sum += unsafe { a.get_unchecked(i << bits | k) * b.get_unchecked(k << bits | j) };\n            }\n            dest[i << bits | j] = sum;\n        }\n    }\n}\n\n// Iterator that counts in interleaved bits.\n// e.g. 0b0, 0b1, 0b100, 0b101, 0b10000, 0b10001, ...\nstruct SplayedBitsCounter {\n    value: usize,\n    max: usize,\n}\n\nimpl SplayedBitsCounter {\n    fn new(max: usize) -> Self {\n        SplayedBitsCounter { value: 0, max }\n    }\n}\n\nimpl Iterator for SplayedBitsCounter {\n    type Item = usize;\n\n    fn next(&mut self) -> Option<usize> {\n        // Return only odd bits.\n        let prev = self.value & 0x5555_5555;\n        if prev < self.max {\n            // Set all even bits.\n            self.value |= 0xaaaa_aaaa;\n            // Add one, carrying through even bits.\n            self.value += 1;\n            Some(prev)\n        } else {\n            None\n        }\n    }\n}\n\n#[test]\nfn test_splayed_counter() {\n    let bits: Vec<usize> = SplayedBitsCounter::new(64).collect();\n    assert_eq!(\n        vec![0b0, 0b1, 0b100, 0b101, 0b10000, 0b10001, 0b10100, 0b10101],\n        bits\n    );\n}\n\n// Multiply the matrices laid out in z order.\n// https://en.wikipedia.org/wiki/Z-order_curve\n#[inline(never)]\npub fn seq_matmulz(a: &[f32], b: &[f32], dest: &mut [f32]) {\n    // All inputs need to be the same length.\n    assert!(a.len() == b.len() && a.len() == dest.len());\n    // Input matrices must be square with each side a power of 2.\n    assert!(a.len().count_ones() == 1 && a.len().trailing_zeros() % 2 == 0);\n    // Zero dest, as it may be uninitialized.\n    for d in dest.iter_mut() {\n        *d = 0.0;\n    }\n\n    // Multiply in morton order\n    // D[i,j] = sum for all k A[i,k] * B[k,j]\n    let n = dest.len();\n    for (ij, d) in dest.iter_mut().enumerate() {\n        let i = ij & 0xaaaa_aaaa;\n        let j = ij & 0x5555_5555;\n        let mut sum = 0.0;\n        for k in SplayedBitsCounter::new(n) {\n            // sum += a[i, k] * b[k, j];\n            sum += unsafe {\n                // If n is a power of 4: i, j, or k should produce\n                // no bits outside a valid index of n.\n                a.get_unchecked(i | k) * b.get_unchecked(k << 1 | j)\n            };\n        }\n        *d = sum;\n    }\n}\n\n#[allow(clippy::identity_op)]\nconst MULT_CHUNK: usize = 1 * 1024;\nconst LINEAR_CHUNK: usize = 64 * 1024;\n\nfn quarter_chunks(v: &[f32]) -> (&[f32], &[f32], &[f32], &[f32]) {\n    let mid = v.len() / 2;\n    let quarter = mid / 2;\n    let (left, right) = v.split_at(mid);\n    let (a, b) = left.split_at(quarter);\n    let (c, d) = right.split_at(quarter);\n    (a, b, c, d)\n}\n\nfn quarter_chunks_mut(v: &mut [f32]) -> (&mut [f32], &mut [f32], &mut [f32], &mut [f32]) {\n    let mid = v.len() / 2;\n    let quarter = mid / 2;\n    let (left, right) = v.split_at_mut(mid);\n    let (a, b) = left.split_at_mut(quarter);\n    let (c, d) = right.split_at_mut(quarter);\n    (a, b, c, d)\n}\n\nfn join4<F1, F2, F3, F4, R1, R2, R3, R4>(f1: F1, f2: F2, f3: F3, f4: F4) -> (R1, R2, R3, R4)\nwhere\n    F1: FnOnce() -> R1 + Send,\n    R1: Send,\n    F2: FnOnce() -> R2 + Send,\n    R2: Send,\n    F3: FnOnce() -> R3 + Send,\n    R3: Send,\n    F4: FnOnce() -> R4 + Send,\n    R4: Send,\n{\n    let ((r1, r2), (r3, r4)) = rayon::join(|| rayon::join(f1, f2), || rayon::join(f3, f4));\n    (r1, r2, r3, r4)\n}\n\n#[allow(clippy::too_many_arguments)]\nfn join8<F1, F2, F3, F4, F5, F6, F7, F8, R1, R2, R3, R4, R5, R6, R7, R8>(\n    f1: F1,\n    f2: F2,\n    f3: F3,\n    f4: F4,\n    f5: F5,\n    f6: F6,\n    f7: F7,\n    f8: F8,\n) -> (R1, R2, R3, R4, R5, R6, R7, R8)\nwhere\n    F1: FnOnce() -> R1 + Send,\n    R1: Send,\n    F2: FnOnce() -> R2 + Send,\n    R2: Send,\n    F3: FnOnce() -> R3 + Send,\n    R3: Send,\n    F4: FnOnce() -> R4 + Send,\n    R4: Send,\n    F5: FnOnce() -> R5 + Send,\n    R5: Send,\n    F6: FnOnce() -> R6 + Send,\n    R6: Send,\n    F7: FnOnce() -> R7 + Send,\n    R7: Send,\n    F8: FnOnce() -> R8 + Send,\n    R8: Send,\n{\n    let (((r1, r2), (r3, r4)), ((r5, r6), (r7, r8))) = rayon::join(\n        || rayon::join(|| rayon::join(f1, f2), || rayon::join(f3, f4)),\n        || rayon::join(|| rayon::join(f5, f6), || rayon::join(f7, f8)),\n    );\n    (r1, r2, r3, r4, r5, r6, r7, r8)\n}\n\n// Multiply two square power of two matrices, given in Z-order.\npub fn matmulz(a: &[f32], b: &[f32], dest: &mut [f32]) {\n    if a.len() <= MULT_CHUNK {\n        seq_matmulz(a, b, dest);\n        return;\n    }\n\n    // Allocate uninitialized scratch space.\n    let mut tmp = raw_buffer(dest.len());\n\n    let (a1, a2, a3, a4) = quarter_chunks(a);\n    let (b1, b2, b3, b4) = quarter_chunks(b);\n    {\n        let (d1, d2, d3, d4) = quarter_chunks_mut(dest);\n        let (t1, t2, t3, t4) = quarter_chunks_mut(&mut tmp[..]);\n        // Multiply 8 submatrices\n        join8(\n            || matmulz(a1, b1, d1),\n            || matmulz(a1, b2, d2),\n            || matmulz(a3, b1, d3),\n            || matmulz(a3, b2, d4),\n            || matmulz(a2, b3, t1),\n            || matmulz(a2, b4, t2),\n            || matmulz(a4, b3, t3),\n            || matmulz(a4, b4, t4),\n        );\n    }\n\n    // Sum each quarter\n    rmatsum(tmp.as_mut(), dest);\n}\n\npub fn matmul_strassen(a: &[f32], b: &[f32], dest: &mut [f32]) {\n    if a.len() <= MULT_CHUNK {\n        seq_matmulz(a, b, dest);\n        return;\n    }\n\n    // Naming taken from https://en.wikipedia.org/wiki/Strassen_algorithm\n    let (a11, a12, a21, a22) = quarter_chunks(a);\n    let (b11, b12, b21, b22) = quarter_chunks(b);\n    // 7 submatrix multiplies.\n    // Maybe the tree should be leaning the other way...\n    let (m1, m2, m3, m4, m5, m6, m7, _) = join8(\n        || strassen_add2_mul(a11, a22, b11, b22),\n        || strassen_add_mul(a21, a22, b11),\n        || strassen_sub_mul(b12, b22, a11),\n        || strassen_sub_mul(b21, b11, a22),\n        || strassen_add_mul(a11, a12, b22),\n        || strassen_sub_add_mul(a21, a11, b11, b12),\n        || strassen_sub_add_mul(a12, a22, b21, b22),\n        || (),\n    );\n\n    // Sum results into dest.\n    let (c11, c12, c21, c22) = quarter_chunks_mut(dest);\n    join4(\n        || strassen_sum_sub(&m1[..], &m4[..], &m7[..], &m5[..], c11),\n        || strassen_sum(&m3[..], &m5[..], c12),\n        || strassen_sum(&m2[..], &m4[..], c21),\n        || strassen_sum_sub(&m1[..], &m3[..], &m6[..], &m2[..], c22),\n    );\n}\n\nfn raw_buffer(n: usize) -> Vec<f32> {\n    // A zero-initialized buffer is fast enough for our purposes.\n    vec![0f32; n]\n}\n\nfn strassen_add2_mul(a1: &[f32], a2: &[f32], b1: &[f32], b2: &[f32]) -> Vec<f32> {\n    let mut dest = raw_buffer(a1.len());\n    let (a, b) = rayon::join(|| rtmp_sum(a1, a2), || rtmp_sum(b1, b2));\n    matmul_strassen(&a[..], &b[..], &mut dest[..]);\n    dest\n}\n\nfn strassen_sub_add_mul(a1: &[f32], a2: &[f32], b1: &[f32], b2: &[f32]) -> Vec<f32> {\n    let mut dest = raw_buffer(a1.len());\n    let (a, b) = rayon::join(|| rtmp_sub(a1, a2), || rtmp_sum(b1, b2));\n    matmul_strassen(&a[..], &b[..], &mut dest[..]);\n    dest\n}\n\nfn strassen_add_mul(a1: &[f32], a2: &[f32], b: &[f32]) -> Vec<f32> {\n    let mut dest = raw_buffer(a1.len());\n    let a = rtmp_sum(a1, a2);\n    matmul_strassen(&a[..], b, &mut dest[..]);\n    dest\n}\n\nfn strassen_sub_mul(b1: &[f32], b2: &[f32], a: &[f32]) -> Vec<f32> {\n    let mut dest = raw_buffer(a.len());\n    let b = rtmp_sub(b1, b2);\n    matmul_strassen(a, &b[..], &mut dest[..]);\n    dest\n}\n\nfn strassen_sum_sub(a: &[f32], b: &[f32], c: &[f32], s: &[f32], dest: &mut [f32]) {\n    rcopy(a, dest);\n    rmatsum(b, dest);\n    rmatsum(c, dest);\n    rmatsub(s, dest);\n}\n\nfn strassen_sum(a: &[f32], b: &[f32], dest: &mut [f32]) {\n    rcopy(a, dest);\n    rmatsum(b, dest);\n}\n\nfn rtmp_sum(a: &[f32], b: &[f32]) -> Vec<f32> {\n    let mut tmp = raw_buffer(a.len());\n    rcopy(a, &mut tmp[..]);\n    rmatsum(b, &mut tmp[..]);\n    tmp\n}\n\nfn rtmp_sub(a: &[f32], b: &[f32]) -> Vec<f32> {\n    let mut tmp = raw_buffer(a.len());\n    rcopy(a, &mut tmp[..]);\n    rmatsub(b, &mut tmp[..]);\n    tmp\n}\n\n// Any layout works, we're just adding by element.\nfn rmatsum(src: &[f32], dest: &mut [f32]) {\n    dest.par_iter_mut()\n        .zip(src.par_iter())\n        .for_each(|(d, s)| *d += *s);\n}\n\nfn rmatsub(src: &[f32], dest: &mut [f32]) {\n    dest.par_iter_mut()\n        .zip(src.par_iter())\n        .for_each(|(d, s)| *d -= *s);\n}\n\nfn rcopy(src: &[f32], dest: &mut [f32]) {\n    if dest.len() <= LINEAR_CHUNK {\n        dest.copy_from_slice(src);\n        return;\n    }\n\n    let mid = dest.len() / 2;\n    let (s1, s2) = src.split_at(mid);\n    let (d1, d2) = dest.split_at_mut(mid);\n    rayon::join(|| rcopy(s1, d1), || rcopy(s2, d2));\n}\n\n#[test]\nfn test_matmul() {\n    // Verify that small matrix gets the right result.\n    let a: Vec<f32> = vec![1.0, 2.0, 3.0, 4.0];\n    let b: Vec<f32> = vec![5.0, 6.0, 7.0, 8.0];\n    let mul: Vec<f32> = vec![19.0, 22.0, 43.0, 50.0];\n    let mut dest = vec![0f32; 4];\n    matmulz(&a[..], &b[..], &mut dest[..]);\n    assert_eq!(mul, dest);\n\n    seq_matmulz(&a[..], &b[..], &mut dest[..]);\n    assert_eq!(mul, dest);\n\n    matmul_strassen(&a[..], &b[..], &mut dest[..]);\n    assert_eq!(mul, dest);\n\n    // Verify that large matrix gets the same results in parallel and serial algorithms.\n    let n = 1 << 14;\n    assert!(n > MULT_CHUNK); // If we don't recurse we're not testing much.\n    let a: Vec<f32> = (0..n).map(|i| (i % 101) as f32).collect();\n    let b: Vec<f32> = (0..n).map(|i| (i % 101 + 7) as f32).collect();\n    let mut seqmul = vec![0f32; n];\n    seq_matmulz(&a[..], &b[..], &mut seqmul[..]);\n    let mut rmul = vec![0f32; n];\n    matmulz(&a[..], &b[..], &mut rmul[..]);\n    assert_eq!(rmul, seqmul);\n\n    // Verify strassen gets the same results.\n    for d in rmul.iter_mut() {\n        *d = 0.0;\n    }\n    matmul_strassen(&a[..], &b[..], &mut rmul[..]);\n    assert_eq!(rmul, seqmul);\n}\n\nfn timed_matmul<F: FnOnce(&[f32], &[f32], &mut [f32])>(size: usize, f: F, name: &str) -> u64 {\n    let size = size.next_power_of_two();\n    let n = size * size;\n    let mut a = vec![0f32; n];\n    let mut b = vec![0f32; n];\n    for i in 0..n {\n        a[i] = i as f32;\n        b[i] = (i + 7) as f32;\n    }\n    let mut dest = vec![0f32; n];\n\n    let start = Instant::now();\n    f(&a[..], &b[..], &mut dest[..]);\n    let dur = Instant::now() - start;\n    let nanos = u64::from(dur.subsec_nanos()) + dur.as_secs() * 1_000_000_000u64;\n    println!(\n        \"{}:\\t{}x{} matrix: {} s\",\n        name,\n        size,\n        size,\n        nanos as f32 / 1e9f32\n    );\n    nanos\n}\n\npub fn main(args: &[String]) {\n    let args: Args = Docopt::new(USAGE)\n        .and_then(|d| d.argv(args).deserialize())\n        .unwrap_or_else(|e| e.exit());\n\n    if args.cmd_bench {\n        if args.flag_size <= 1024 {\n            // Crappy algorithm takes several minutes on larger inputs.\n            timed_matmul(args.flag_size, seq_matmul, \"seq row-major\");\n        }\n        let seq = if args.flag_size <= 2048 {\n            timed_matmul(args.flag_size, seq_matmulz, \"seq z-order\")\n        } else {\n            0\n        };\n        let par = timed_matmul(args.flag_size, matmulz, \"par z-order\");\n        timed_matmul(args.flag_size, matmul_strassen, \"par strassen\");\n        let speedup = seq as f64 / par as f64;\n        println!(\"speedup: {speedup:.2}x\");\n    }\n}\n\n#[cfg(test)]\nmod bench;\n"
  },
  {
    "path": "rayon-demo/src/mergesort/bench.rs",
    "content": "// Size to use when doing `cargo bench`; extensively tuned to run in\n// \"not too long\" on my laptop -nmatsakis\nconst BENCH_SIZE: usize = 250_000_000 / 512;\n\nfn bench_harness<F: FnMut(&mut [u32])>(mut f: F, b: &mut test::Bencher) {\n    let base_vec = super::default_vec(BENCH_SIZE);\n    let mut sort_vec = base_vec.clone();\n    b.iter(|| {\n        sort_vec.clone_from(&base_vec);\n        f(&mut sort_vec);\n    });\n    assert!(super::is_sorted(&mut sort_vec));\n}\n\n#[bench]\nfn merge_sort_par_bench(b: &mut test::Bencher) {\n    bench_harness(super::merge_sort, b);\n}\n\n#[bench]\nfn merge_sort_seq_bench(b: &mut test::Bencher) {\n    bench_harness(super::seq_merge_sort, b);\n}\n"
  },
  {
    "path": "rayon-demo/src/mergesort/mod.rs",
    "content": "use rand::distr::StandardUniform;\nuse rand::Rng;\n\nconst USAGE: &str = \"\nUsage: mergesort bench [--size N]\n       mergesort --help\n\nParallel mergesort: regular sorting with a parallel merge step.\nO(n log n) time; O(n) extra space; critical path is O(log^3 n)\n\nAlgorithm described in: https://software.intel.com/en-us/articles/a-parallel-stable-sort-using-c11-for-tbb-cilk-plus-and-openmp\n\nCommands:\n    bench              Run the benchmark in different modes and print the timings.\n\nOptions:\n    --size N           Number of 32-bit words to sort [default: 250000000] (1GB)\n    -h, --help         Show this message.\n\";\n\n#[derive(serde::Deserialize)]\npub struct Args {\n    cmd_bench: bool,\n    flag_size: usize,\n}\n\nuse docopt::Docopt;\n\nuse std::mem::MaybeUninit;\nuse std::slice;\nuse std::time::Instant;\n\npub fn merge_sort<T: Ord + Send + Copy>(v: &mut [T]) {\n    let n = v.len();\n    let mut buf: Vec<MaybeUninit<T>> = Vec::with_capacity(n);\n    // SAFETY: MaybeUninit can be uninitialized\n    unsafe {\n        buf.set_len(n);\n    }\n    rsort(v, &mut buf[..]);\n}\n\n// Values from manual tuning gigasort on one machine.\nconst SORT_CHUNK: usize = 32 * 1024;\nconst MERGE_CHUNK: usize = 64 * 1024;\n\nfn as_uninit_slice<T: Copy>(slice: &[T]) -> &[MaybeUninit<T>] {\n    let len = slice.len();\n    // SAFETY: MaybeUninit is transparent to T, and we're only dealing with T: Copy\n    unsafe { slice::from_raw_parts(slice.as_ptr().cast(), len) }\n}\n\nfn as_uninit_slice_mut<T: Copy>(slice: &mut [T]) -> &mut [MaybeUninit<T>] {\n    let len = slice.len();\n    // SAFETY: MaybeUninit is transparent to T, and we're only dealing with T: Copy\n    unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), len) }\n}\n\nunsafe fn slice_assume_init_mut<T>(slice: &mut [MaybeUninit<T>]) -> &mut [T] {\n    let len = slice.len();\n    slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), len)\n}\n\n// Sort src, possibly making use of identically sized buf.\nfn rsort<T: Ord + Send + Copy>(src: &mut [T], buf: &mut [MaybeUninit<T>]) {\n    if src.len() <= SORT_CHUNK {\n        src.sort();\n        return;\n    }\n\n    // Sort each half into half of the buffer.\n    let mid = src.len() / 2;\n    let (sa, sb) = src.split_at_mut(mid);\n    let (bufa, bufb) = buf.split_at_mut(mid);\n    let (sorta, sortb) = rayon::join(|| rsort_into(sa, bufa), || rsort_into(sb, bufb));\n\n    // Merge the buffer halves back into the original.\n    rmerge(sorta, sortb, as_uninit_slice_mut(src));\n}\n\n// Sort src, putting the result into dest.\nfn rsort_into<'dest, T: Ord + Send + Copy>(\n    src: &mut [T],\n    dest: &'dest mut [MaybeUninit<T>],\n) -> &'dest mut [T] {\n    let mid = src.len() / 2;\n    let (s1, s2) = src.split_at_mut(mid);\n    {\n        // Sort each half.\n        let (d1, d2) = dest.split_at_mut(mid);\n        rayon::join(|| rsort(s1, d1), || rsort(s2, d2));\n    }\n\n    // Merge the halves into dest.\n    rmerge(s1, s2, dest);\n    unsafe { slice_assume_init_mut(dest) }\n}\n\n// Merge sorted inputs a and b, putting result in dest.\n//\n// Note: `a` and `b` have type `&mut [T]` and not `&[T]` because we do\n// not want to require a `T: Sync` bound. Using `&mut` references\n// proves to the compiler that we are not sharing `a` and `b` across\n// threads and thus we only need a `T: Send` bound.\nfn rmerge<T: Ord + Send + Copy>(a: &mut [T], b: &mut [T], dest: &mut [MaybeUninit<T>]) {\n    // Swap so a is always longer.\n    let (a, b) = if a.len() > b.len() { (a, b) } else { (b, a) };\n    if dest.len() <= MERGE_CHUNK {\n        seq_merge(a, b, dest);\n        return;\n    }\n\n    // Find the middle element of the longer list, and\n    // use binary search to find its location in the shorter list.\n    let ma = a.len() / 2;\n    let mb = match b.binary_search(&a[ma]) {\n        Ok(i) => i,\n        Err(i) => i,\n    };\n\n    let (a1, a2) = a.split_at_mut(ma);\n    let (b1, b2) = b.split_at_mut(mb);\n    let (d1, d2) = dest.split_at_mut(ma + mb);\n    rayon::join(|| rmerge(a1, b1, d1), || rmerge(a2, b2, d2));\n}\n\n// Merges sorted a and b into sorted dest.\n#[inline(never)]\nfn seq_merge<T: Ord + Copy>(a: &[T], b: &[T], dest: &mut [MaybeUninit<T>]) {\n    if b.is_empty() {\n        dest.copy_from_slice(as_uninit_slice(a));\n        return;\n    }\n    let biggest = Ord::max(*a.last().unwrap(), *b.last().unwrap());\n    let mut ai = a.iter();\n    let mut an = *ai.next().unwrap();\n    let mut bi = b.iter();\n    let mut bn = *bi.next().unwrap();\n    for d in dest.iter_mut() {\n        if an < bn {\n            *d = MaybeUninit::new(an);\n            an = match ai.next() {\n                Some(x) => *x,\n                None => biggest,\n            }\n        } else {\n            *d = MaybeUninit::new(bn);\n            bn = match bi.next() {\n                Some(x) => *x,\n                None => biggest,\n            }\n        }\n    }\n}\n\n#[test]\nfn test_merge_sort() {\n    let mut v = vec![1; 200_000];\n    merge_sort(&mut v[..]);\n\n    let sorted: Vec<u32> = (1..1_000_000).collect();\n    let mut v = sorted.clone();\n    merge_sort(&mut v[..]);\n    assert_eq!(sorted, v);\n\n    v.reverse();\n    merge_sort(&mut v[..]);\n    assert_eq!(sorted, v);\n}\n\npub fn seq_merge_sort<T: Ord + Copy>(v: &mut [T]) {\n    let n = v.len();\n    let mut buf: Vec<MaybeUninit<T>> = Vec::with_capacity(n);\n    // SAFETY: MaybeUninit can be uninitialized\n    unsafe {\n        buf.set_len(n);\n    }\n    seq_sort(v, &mut buf[..]);\n}\n\n// Sort src, possibly making use of identically sized buf.\nfn seq_sort<T: Ord + Copy>(src: &mut [T], buf: &mut [MaybeUninit<T>]) {\n    if src.len() <= SORT_CHUNK {\n        src.sort();\n        return;\n    }\n\n    // Sort each half into half of the buffer.\n    let mid = src.len() / 2;\n    let (sa, sb) = src.split_at_mut(mid);\n    let (bufa, bufb) = buf.split_at_mut(mid);\n    let (sorta, sortb) = (seq_sort_into(sa, bufa), seq_sort_into(sb, bufb));\n\n    // Merge the buffer halves back into the original.\n    seq_merge(sorta, sortb, as_uninit_slice_mut(src));\n}\n\n// Sort src, putting the result into dest.\nfn seq_sort_into<'dest, T: Ord + Copy>(\n    src: &mut [T],\n    dest: &'dest mut [MaybeUninit<T>],\n) -> &'dest mut [T] {\n    let mid = src.len() / 2;\n    let (s1, s2) = src.split_at_mut(mid);\n    {\n        // Sort each half.\n        let (d1, d2) = dest.split_at_mut(mid);\n        seq_sort(s1, d1);\n        seq_sort(s2, d2);\n    }\n\n    // Merge the halves into dest.\n    seq_merge(s1, s2, dest);\n    unsafe { slice_assume_init_mut(dest) }\n}\n\npub fn is_sorted<T: Send + Ord>(v: &mut [T]) -> bool {\n    let n = v.len();\n    if n <= SORT_CHUNK {\n        for i in 1..n {\n            if v[i - 1] > v[i] {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    let mid = n / 2;\n    if v[mid - 1] > v[mid] {\n        return false;\n    }\n    let (a, b) = v.split_at_mut(mid);\n    let (left, right) = rayon::join(|| is_sorted(a), || is_sorted(b));\n    left && right\n}\n\nfn default_vec(n: usize) -> Vec<u32> {\n    let rng = crate::seeded_rng();\n    rng.sample_iter(&StandardUniform).take(n).collect()\n}\n\nfn timed_sort<F: FnOnce(&mut [u32])>(n: usize, f: F, name: &str) -> u64 {\n    let mut v = default_vec(n);\n\n    let start = Instant::now();\n    f(&mut v[..]);\n    let dur = Instant::now() - start;\n    let nanos = u64::from(dur.subsec_nanos()) + dur.as_secs() * 1_000_000_000u64;\n    println!(\"{}: sorted {} ints: {} s\", name, n, nanos as f32 / 1e9f32);\n\n    // Check correctness\n    assert!(is_sorted(&mut v[..]));\n\n    nanos\n}\n\npub fn main(args: &[String]) {\n    let args: Args = Docopt::new(USAGE)\n        .and_then(|d| d.argv(args).deserialize())\n        .unwrap_or_else(|e| e.exit());\n\n    if args.cmd_bench {\n        let seq = timed_sort(args.flag_size, seq_merge_sort, \"seq\");\n        let par = timed_sort(args.flag_size, merge_sort, \"par\");\n        let speedup = seq as f64 / par as f64;\n        println!(\"speedup: {speedup:.2}x\");\n    }\n}\n\n#[cfg(test)]\nmod bench;\n"
  },
  {
    "path": "rayon-demo/src/nbody/bench.rs",
    "content": "use super::nbody::NBodyBenchmark;\n\n// Because benchmarks run iteratively, use smaller constants by default:\nconst BENCH_BODIES: usize = 1000;\n\nconst BENCH_TICKS: usize = 10;\n\nfn nbody_bench<TICK>(b: &mut test::Bencher, mut tick: TICK)\nwhere\n    TICK: FnMut(&mut NBodyBenchmark),\n{\n    let mut rng = crate::seeded_rng();\n    let mut benchmark = NBodyBenchmark::new(BENCH_BODIES, &mut rng);\n    b.iter(|| {\n        for _ in 0..BENCH_TICKS {\n            tick(&mut benchmark);\n        }\n    });\n}\n\n#[bench]\nfn nbody_seq(b: &mut ::test::Bencher) {\n    nbody_bench(b, |n| {\n        n.tick_seq();\n    });\n}\n\n#[bench]\nfn nbody_par_iter(b: &mut ::test::Bencher) {\n    nbody_bench(b, |n| {\n        n.tick_par();\n    });\n}\n\n#[bench]\nfn nbody_par_bridge(b: &mut ::test::Bencher) {\n    nbody_bench(b, |n| {\n        n.tick_par_bridge();\n    });\n}\n\n#[bench]\nfn nbody_parreduce(b: &mut ::test::Bencher) {\n    nbody_bench(b, |n| {\n        n.tick_par_reduce();\n    });\n}\n"
  },
  {
    "path": "rayon-demo/src/nbody/mod.rs",
    "content": "use docopt::Docopt;\nuse std::time::Instant;\n\n#[cfg(test)]\nmod bench;\n#[allow(clippy::module_inception)]\nmod nbody;\nmod visualize;\nuse self::nbody::NBodyBenchmark;\nuse self::visualize::visualize_benchmarks;\n\nconst USAGE: &str = \"\nUsage: nbody bench [--mode MODE --bodies N --ticks N]\n       nbody visualize [--mode MODE --bodies N]\n       nbody --help\n\nPhysics simulation of multiple bodies alternatively attracting and\nrepelling one another. Visualizable with OpenGL.\n\nCommands:\n    bench              Run the benchmark and print the timings.\n    visualize          Show the graphical visualizer.\n\nOptions:\n    -h, --help         Show this message.\n    --mode MODE        Execution mode for the benchmark/visualizer.\n    --bodies N         Use N bodies [default: 4000].\n    --ticks N          Simulate for N ticks [default: 100].\n\n\nCommands:\n    bench              Run the benchmark and print the timings.\n    visualize          Show the graphical visualizer.\n\nOptions:\n    -h, --help         Show this message.\n    --mode MODE        Execution mode for the benchmark/visualizer.\n                       MODE can one of 'par', 'seq', or 'parreduce'.\n    --bodies N         Use N bodies [default: 4000].\n    --ticks N          Simulate for N ticks [default: 100].\n\nPorted from the RiverTrail demo found at:\n    https://github.com/IntelLabs/RiverTrail/tree/master/examples/nbody-webgl\n\";\n\n#[derive(Copy, Clone, PartialEq, Eq, serde::Deserialize)]\npub enum ExecutionMode {\n    Par,\n    ParReduce,\n    Seq,\n}\n\n#[derive(serde::Deserialize)]\npub struct Args {\n    cmd_bench: bool,\n    cmd_visualize: bool,\n    flag_mode: Option<ExecutionMode>,\n    flag_bodies: usize,\n    flag_ticks: usize,\n}\n\npub fn main(args: &[String]) {\n    let args: Args = Docopt::new(USAGE)\n        .and_then(|d| d.argv(args).deserialize())\n        .unwrap_or_else(|e| e.exit());\n\n    if args.cmd_bench {\n        run_benchmarks(args.flag_mode, args.flag_bodies, args.flag_ticks);\n    }\n\n    if args.cmd_visualize {\n        visualize_benchmarks(\n            args.flag_bodies,\n            args.flag_mode.unwrap_or(ExecutionMode::Par),\n        );\n    }\n}\n\nfn run_benchmarks(mode: Option<ExecutionMode>, bodies: usize, ticks: usize) {\n    let run_par = mode.map(|m| m == ExecutionMode::Par).unwrap_or(true);\n    let run_par_reduce = mode.map(|m| m == ExecutionMode::ParReduce).unwrap_or(true);\n    let run_seq = mode.map(|m| m == ExecutionMode::Seq).unwrap_or(true);\n\n    let par_time = if run_par {\n        let mut rng = crate::seeded_rng();\n        let mut benchmark = NBodyBenchmark::new(bodies, &mut rng);\n        let par_start = Instant::now();\n\n        for _ in 0..ticks {\n            benchmark.tick_par();\n        }\n\n        let par_time = par_start.elapsed().as_nanos();\n        println!(\"Parallel time    : {par_time} ns\");\n\n        Some(par_time)\n    } else {\n        None\n    };\n\n    let par_reduce_time = if run_par_reduce {\n        let mut rng = crate::seeded_rng();\n        let mut benchmark = NBodyBenchmark::new(bodies, &mut rng);\n        let par_start = Instant::now();\n\n        for _ in 0..ticks {\n            benchmark.tick_par_reduce();\n        }\n\n        let par_time = par_start.elapsed().as_nanos();\n        println!(\"ParReduce time   : {par_time} ns\");\n\n        Some(par_time)\n    } else {\n        None\n    };\n\n    let seq_time = if run_seq {\n        let mut rng = crate::seeded_rng();\n        let mut benchmark = NBodyBenchmark::new(bodies, &mut rng);\n        let seq_start = Instant::now();\n\n        for _ in 0..ticks {\n            benchmark.tick_seq();\n        }\n\n        let seq_time = seq_start.elapsed().as_nanos();\n        println!(\"Sequential time  : {seq_time} ns\");\n\n        Some(seq_time)\n    } else {\n        None\n    };\n\n    if let (Some(pt), Some(st)) = (par_time, seq_time) {\n        println!(\"Parallel speedup : {}\", (st as f32) / (pt as f32));\n    }\n\n    if let (Some(pt), Some(st)) = (par_reduce_time, seq_time) {\n        println!(\"ParReduce speedup: {}\", (st as f32) / (pt as f32));\n    }\n}\n"
  },
  {
    "path": "rayon-demo/src/nbody/nbody.rs",
    "content": "// Rust source (c) 2016 by the Rayon developers. This is ported from\n// [JavaScript sources][1] developed by Intel as part of the Parallel\n// JS project. The copyright for the original source is reproduced\n// below.\n//\n// Copyright (c) 2011, Intel Corporation\n// All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are met:\n//\n// - Redistributions of source code must retain the above copyright notice,\n//   this list of conditions and the following disclaimer.\n// - Redistributions in binary form must reproduce the above copyright notice,\n//   this list of conditions and the following disclaimer in the documentation\n//   and/or other materials provided with the distribution.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n// THE POSSIBILITY OF SUCH DAMAGE.\n//\n// [1]: https://github.com/IntelLabs/RiverTrail/blob/master/examples/nbody-webgl/NBody.js\n\nuse cgmath::{InnerSpace, Point3, Vector3, Zero};\nuse rand::Rng;\nuse rayon::prelude::*;\nuse std::f64::consts::PI;\n\nconst INITIAL_VELOCITY: f64 = 8.0; // set to 0.0 to turn off.\n\npub struct NBodyBenchmark {\n    time: usize,\n    bodies: (Vec<Body>, Vec<Body>),\n}\n\n#[derive(Copy, Clone, Debug)]\npub struct Body {\n    pub position: Point3<f64>,\n    pub velocity: Vector3<f64>,\n    pub velocity2: Vector3<f64>,\n}\n\nimpl NBodyBenchmark {\n    pub fn new<R: Rng>(num_bodies: usize, rng: &mut R) -> NBodyBenchmark {\n        let bodies0: Vec<_> = (0..num_bodies)\n            .map(|_| {\n                let r = rng.random_range(0.0..10_000.0);\n                let theta = rng.random_range(0.0..PI);\n                let phi = rng.random_range(0.0..2.0 * PI);\n                let position = Point3 {\n                    x: r * theta.sin() * phi.cos(),\n                    y: r * theta.sin() * phi.sin(),\n                    z: r * theta.cos(),\n                };\n\n                let velocity = Vector3 {\n                    x: rng.random_range(-0.5..0.5) * INITIAL_VELOCITY,\n                    y: rng.random_range(-0.5..0.5) * INITIAL_VELOCITY,\n                    z: rng.random::<f64>() * INITIAL_VELOCITY + 10.0,\n                };\n\n                let velocity2 = Vector3 {\n                    x: rng.random_range(-0.5..0.5) * INITIAL_VELOCITY,\n                    y: rng.random_range(-0.5..0.5) * INITIAL_VELOCITY,\n                    z: rng.random::<f64>() * INITIAL_VELOCITY,\n                };\n\n                Body {\n                    position,\n                    velocity,\n                    velocity2,\n                }\n            })\n            .collect();\n\n        let bodies1 = bodies0.clone();\n\n        NBodyBenchmark {\n            time: 0,\n            bodies: (bodies0, bodies1),\n        }\n    }\n\n    pub fn tick_par(&mut self) -> &[Body] {\n        let (in_bodies, out_bodies) = if (self.time & 1) == 0 {\n            (&self.bodies.0, &mut self.bodies.1)\n        } else {\n            (&self.bodies.1, &mut self.bodies.0)\n        };\n\n        let time = self.time;\n        out_bodies\n            .par_iter_mut()\n            .zip(&in_bodies[..])\n            .for_each(|(out, prev)| {\n                let (vel, vel2) = next_velocity(time, prev, in_bodies);\n                out.velocity = vel;\n                out.velocity2 = vel2;\n\n                let next_velocity = vel - vel2;\n                out.position = prev.position + next_velocity;\n            });\n\n        self.time += 1;\n\n        out_bodies\n    }\n\n    #[cfg(test)]\n    pub fn tick_par_bridge(&mut self) -> &[Body] {\n        let (in_bodies, out_bodies) = if (self.time & 1) == 0 {\n            (&self.bodies.0, &mut self.bodies.1)\n        } else {\n            (&self.bodies.1, &mut self.bodies.0)\n        };\n\n        let time = self.time;\n        out_bodies\n            .iter_mut()\n            .zip(&in_bodies[..])\n            .par_bridge()\n            .for_each(|(out, prev)| {\n                let (vel, vel2) = next_velocity(time, prev, in_bodies);\n                out.velocity = vel;\n                out.velocity2 = vel2;\n\n                let next_velocity = vel - vel2;\n                out.position = prev.position + next_velocity;\n            });\n\n        self.time += 1;\n\n        out_bodies\n    }\n\n    pub fn tick_par_reduce(&mut self) -> &[Body] {\n        let (in_bodies, out_bodies) = if (self.time & 1) == 0 {\n            (&self.bodies.0, &mut self.bodies.1)\n        } else {\n            (&self.bodies.1, &mut self.bodies.0)\n        };\n\n        let time = self.time;\n        out_bodies\n            .par_iter_mut()\n            .zip(&in_bodies[..])\n            .for_each(|(out, prev)| {\n                let (vel, vel2) = next_velocity_par(time, prev, in_bodies);\n                out.velocity = vel;\n                out.velocity2 = vel2;\n\n                let next_velocity = vel - vel2;\n                out.position = prev.position + next_velocity;\n            });\n\n        self.time += 1;\n\n        out_bodies\n    }\n\n    pub fn tick_seq(&mut self) -> &[Body] {\n        let (in_bodies, out_bodies) = if (self.time & 1) == 0 {\n            (&self.bodies.0, &mut self.bodies.1)\n        } else {\n            (&self.bodies.1, &mut self.bodies.0)\n        };\n\n        let time = self.time;\n        for (out, prev) in out_bodies.iter_mut().zip(&in_bodies[..]) {\n            let (vel, vel2) = next_velocity(time, prev, in_bodies);\n            out.velocity = vel;\n            out.velocity2 = vel2;\n\n            let next_velocity = vel - vel2;\n            out.position = prev.position + next_velocity;\n        }\n\n        self.time += 1;\n\n        out_bodies\n    }\n}\n\n/// Compute next velocity of `prev`\nfn next_velocity(time: usize, prev: &Body, bodies: &[Body]) -> (Vector3<f64>, Vector3<f64>) {\n    let time = time as f64;\n    let center = Point3 {\n        x: (time / 22.0).cos() * -4200.0,\n        y: (time / 14.0).sin() * 9200.0,\n        z: (time / 27.0).sin() * 6000.0,\n    };\n\n    // pull to center\n    let max_distance = 3400.0;\n    let pull_strength = 0.042;\n\n    // zones\n    let zone = 400.0;\n    let repel = 100.0;\n    let align = 300.0;\n    let attract = 100.0;\n\n    let (speed_limit, attract_power);\n    if time < 500.0 {\n        speed_limit = 2000.0;\n        attract_power = 100.9;\n    } else {\n        speed_limit = 0.2;\n        attract_power = 20.9;\n    }\n\n    let zone_sqrd = 3.0 * (zone * zone);\n\n    let mut acc = Vector3::zero();\n    let mut acc2 = Vector3::zero();\n\n    let dir_to_center = center - prev.position;\n    let dist_to_center = dir_to_center.magnitude();\n\n    // orient to center\n    if dist_to_center > max_distance {\n        let velc = if time < 200.0 {\n            0.2\n        } else {\n            (dist_to_center - max_distance) * pull_strength\n        };\n\n        let diff = (dir_to_center / dist_to_center) * velc;\n        acc += diff;\n    }\n\n    // TODO -- parallelize this loop too? would be easy enough, it's just a reduction\n    // Just have to factor things so that `tick_seq` doesn't do it in parallel.\n    let zero: Vector3<f64> = Vector3::zero();\n    let (diff, diff2) = bodies\n        .iter()\n        .fold((zero, zero), |(mut diff, mut diff2), body| {\n            let r = body.position - prev.position;\n\n            // make sure we are not testing the particle against its own position\n            let are_same = r == Vector3::zero();\n\n            let dist_sqrd = r.magnitude2();\n\n            if dist_sqrd < zone_sqrd && !are_same {\n                let length = dist_sqrd.sqrt();\n                let percent = dist_sqrd / zone_sqrd;\n\n                if dist_sqrd < repel {\n                    let f = (repel / percent - 1.0) * 0.025;\n                    let normal = (r / length) * f;\n                    diff += normal;\n                    diff2 += normal;\n                } else if dist_sqrd < align {\n                    let thresh_delta = align - repel;\n                    let adjusted_percent = (percent - repel) / thresh_delta;\n                    let q = (0.5 - (adjusted_percent * PI * 2.0).cos() * 0.5 + 0.5) * 100.9;\n\n                    // normalize vel2 and multiply by factor\n                    let vel2_length = body.velocity2.magnitude();\n                    let vel2 = (body.velocity2 / vel2_length) * q;\n\n                    // normalize own velocity\n                    let vel_length = prev.velocity.magnitude();\n                    let vel = (prev.velocity / vel_length) * q;\n\n                    diff += vel2;\n                    diff2 += vel;\n                }\n\n                if dist_sqrd > attract {\n                    // attract\n                    let thresh_delta2 = 1.0 - attract;\n                    let adjusted_percent2 = (percent - attract) / thresh_delta2;\n                    let c =\n                        (1.0 - ((adjusted_percent2 * PI * 2.0).cos() * 0.5 + 0.5)) * attract_power;\n\n                    // normalize the distance vector\n                    let d = (r / length) * c;\n\n                    diff += d;\n                    diff2 -= d;\n                }\n            }\n\n            (diff, diff2)\n        });\n\n    acc += diff;\n    acc2 += diff2;\n\n    // Speed limits\n    if time > 500.0 {\n        let acc_squared = acc.magnitude2();\n        if acc_squared > speed_limit {\n            acc *= 0.015;\n        }\n\n        let acc_squared2 = acc2.magnitude2();\n        if acc_squared2 > speed_limit {\n            acc2 *= 0.015;\n        }\n    }\n\n    let mut new = prev.velocity + acc;\n    let mut new2 = prev.velocity2 + acc2;\n\n    if time < 500.0 {\n        let acs = new2.magnitude2();\n        if acs > speed_limit {\n            new2 *= 0.15;\n        }\n\n        let acs2 = new.magnitude2();\n        if acs2 > speed_limit {\n            new *= 0.15;\n        }\n    }\n\n    (new, new2)\n}\n\n/// Compute next velocity of `prev`\nfn next_velocity_par(time: usize, prev: &Body, bodies: &[Body]) -> (Vector3<f64>, Vector3<f64>) {\n    let time = time as f64;\n    let center = Point3 {\n        x: (time / 22.0).cos() * -4200.0,\n        y: (time / 14.0).sin() * 9200.0,\n        z: (time / 27.0).sin() * 6000.0,\n    };\n\n    // pull to center\n    let max_distance = 3400.0;\n    let pull_strength = 0.042;\n\n    // zones\n    let zone = 400.0;\n    let repel = 100.0;\n    let align = 300.0;\n    let attract = 100.0;\n\n    let (speed_limit, attract_power);\n    if time < 500.0 {\n        speed_limit = 2000.0;\n        attract_power = 100.9;\n    } else {\n        speed_limit = 0.2;\n        attract_power = 20.9;\n    }\n\n    let zone_sqrd = 3.0 * (zone * zone);\n\n    let mut acc = Vector3::zero();\n    let mut acc2 = Vector3::zero();\n\n    let dir_to_center = center - prev.position;\n    let dist_to_center = dir_to_center.magnitude();\n\n    // orient to center\n    if dist_to_center > max_distance {\n        let velc = if time < 200.0 {\n            0.2\n        } else {\n            (dist_to_center - max_distance) * pull_strength\n        };\n\n        let diff = (dir_to_center / dist_to_center) * velc;\n        acc += diff;\n    }\n\n    let (diff, diff2) = bodies\n        .par_iter()\n        .fold(\n            || (Vector3::zero(), Vector3::zero()),\n            |(mut diff, mut diff2), body| {\n                let r = body.position - prev.position;\n\n                // make sure we are not testing the particle against its own position\n                let are_same = r == Vector3::zero();\n\n                let dist_sqrd = r.magnitude2();\n\n                if dist_sqrd < zone_sqrd && !are_same {\n                    let length = dist_sqrd.sqrt();\n                    let percent = dist_sqrd / zone_sqrd;\n\n                    if dist_sqrd < repel {\n                        let f = (repel / percent - 1.0) * 0.025;\n                        let normal = (r / length) * f;\n                        diff += normal;\n                        diff2 += normal;\n                    } else if dist_sqrd < align {\n                        let thresh_delta = align - repel;\n                        let adjusted_percent = (percent - repel) / thresh_delta;\n                        let q = (0.5 - (adjusted_percent * PI * 2.0).cos() * 0.5 + 0.5) * 100.9;\n\n                        // normalize vel2 and multiply by factor\n                        let vel2_length = body.velocity2.magnitude();\n                        let vel2 = (body.velocity2 / vel2_length) * q;\n\n                        // normalize own velocity\n                        let vel_length = prev.velocity.magnitude();\n                        let vel = (prev.velocity / vel_length) * q;\n\n                        diff += vel2;\n                        diff2 += vel;\n                    }\n\n                    if dist_sqrd > attract {\n                        // attract\n                        let thresh_delta2 = 1.0 - attract;\n                        let adjusted_percent2 = (percent - attract) / thresh_delta2;\n                        let c = (1.0 - ((adjusted_percent2 * PI * 2.0).cos() * 0.5 + 0.5))\n                            * attract_power;\n\n                        // normalize the distance vector\n                        let d = (r / length) * c;\n\n                        diff += d;\n                        diff2 -= d;\n                    }\n                }\n\n                (diff, diff2)\n            },\n        )\n        .reduce(\n            || (Vector3::zero(), Vector3::zero()),\n            |(diffa, diff2a), (diffb, diff2b)| (diffa + diffb, diff2a + diff2b),\n        );\n\n    acc += diff;\n    acc2 += diff2;\n\n    // Speed limits\n    if time > 500.0 {\n        let acc_squared = acc.magnitude2();\n        if acc_squared > speed_limit {\n            acc *= 0.015;\n        }\n\n        let acc_squared2 = acc2.magnitude2();\n        if acc_squared2 > speed_limit {\n            acc2 *= 0.015;\n        }\n    }\n\n    let mut new = prev.velocity + acc;\n    let mut new2 = prev.velocity2 + acc2;\n\n    if time < 500.0 {\n        let acs = new2.magnitude2();\n        if acs > speed_limit {\n            new2 *= 0.15;\n        }\n\n        let acs2 = new.magnitude2();\n        if acs2 > speed_limit {\n            new *= 0.15;\n        }\n    }\n\n    (new, new2)\n}\n"
  },
  {
    "path": "rayon-demo/src/nbody/visualize.rs",
    "content": "use cgmath::{Angle, EuclideanSpace, Matrix4, Point3, Rad, Vector3};\nuse glium::backend::glutin::{Display, SimpleWindowBuilder};\n\nuse glium::glutin::surface::WindowSurface;\nuse glium::index::{IndexBuffer, PrimitiveType};\nuse glium::{Depth, DepthTest, DrawParameters, Program, Surface, VertexBuffer};\nuse rand::Rng;\nuse winit::application::ApplicationHandler;\n\nuse winit::event::{ElementState, KeyEvent, WindowEvent};\nuse winit::event_loop::{ActiveEventLoop, EventLoop};\nuse winit::keyboard::{Key, NamedKey};\nuse winit::window::{Window, WindowId};\n\nuse crate::nbody::nbody::NBodyBenchmark;\nuse crate::nbody::ExecutionMode;\n\n#[derive(Copy, Clone)]\nstruct Vertex {\n    position: [f32; 3],\n}\n\nglium::implement_vertex!(Vertex, position);\n\nfn icosahedron() -> ([Vertex; 12], Vec<u8>) {\n    let phi = (1.0 + f32::sqrt(5.0)) / 2.0;\n\n    let vertices = [\n        Vertex {\n            position: [phi, 1.0, 0.0],\n        },\n        Vertex {\n            position: [phi, -1.0, 0.0],\n        },\n        Vertex {\n            position: [-phi, 1.0, 0.0],\n        },\n        Vertex {\n            position: [-phi, -1.0, 0.0],\n        },\n        Vertex {\n            position: [0.0, phi, 1.0],\n        },\n        Vertex {\n            position: [0.0, phi, -1.0],\n        },\n        Vertex {\n            position: [0.0, -phi, 1.0],\n        },\n        Vertex {\n            position: [0.0, -phi, -1.0],\n        },\n        Vertex {\n            position: [1.0, 0.0, phi],\n        },\n        Vertex {\n            position: [-1.0, 0.0, phi],\n        },\n        Vertex {\n            position: [1.0, 0.0, -phi],\n        },\n        Vertex {\n            position: [-1.0, 0.0, -phi],\n        },\n    ];\n\n    let indices = vec![\n        0, 1, 8, 0, 4, 5, 0, 5, 10, 0, 8, 4, 0, 10, 1, 1, 6, 8, 1, 7, 6, 1, 10, 7, 2, 3, 11, 2, 4,\n        9, 2, 5, 4, 2, 9, 3, 2, 11, 5, 3, 6, 7, 3, 7, 11, 3, 9, 6, 4, 8, 9, 5, 11, 10, 6, 9, 8, 7,\n        10, 11,\n    ];\n\n    (vertices, indices)\n}\n\n#[derive(Copy, Clone)]\nstruct Instance {\n    color: [f32; 3],\n    world_position: [f32; 3],\n}\n\nglium::implement_vertex!(Instance, color, world_position);\n\nstruct State {\n    window: Option<Window>,\n    mode: ExecutionMode,\n    instance_buffer: VertexBuffer<Instance>,\n    benchmark: NBodyBenchmark,\n    display: Display<WindowSurface>,\n    vertex_buffer: VertexBuffer<Vertex>,\n    index_buffer: IndexBuffer<u8>,\n    program: Program,\n}\n\nimpl ApplicationHandler for State {\n    fn resumed(&mut self, _event_loop: &ActiveEventLoop) {}\n\n    fn window_event(\n        &mut self,\n        event_loop: &ActiveEventLoop,\n        _window_id: WindowId,\n        event: WindowEvent,\n    ) {\n        match event {\n            WindowEvent::CloseRequested => event_loop.exit(),\n            WindowEvent::KeyboardInput {\n                event:\n                    KeyEvent {\n                        state: ElementState::Pressed,\n                        logical_key,\n                        ..\n                    },\n                ..\n            } => match logical_key {\n                Key::Named(NamedKey::Escape) => event_loop.exit(),\n                Key::Character(s) => match s.as_str() {\n                    \"p\" => self.mode = ExecutionMode::Par,\n                    \"r\" => self.mode = ExecutionMode::ParReduce,\n                    \"s\" => self.mode = ExecutionMode::Seq,\n                    _ => (),\n                },\n                _ => (),\n            },\n            WindowEvent::RedrawRequested => {\n                let params = DrawParameters {\n                    depth: Depth {\n                        test: DepthTest::IfLess,\n                        write: true,\n                        ..Default::default()\n                    },\n                    ..Default::default()\n                };\n\n                let mut target = self.display.draw();\n\n                let (width, height) = target.get_dimensions();\n                let aspect = width as f32 / height as f32;\n\n                let proj = cgmath::perspective(Rad::full_turn() / 6.0, aspect, 0.1, 3000.0);\n                let view = Matrix4::look_at_rh(\n                    Point3::new(10.0, 10.0, 10.0),\n                    Point3::origin(),\n                    Vector3::unit_z(),\n                );\n                let view_proj: [[f32; 4]; 4] = (proj * view).into();\n\n                target.clear_color_and_depth((0.1, 0.1, 0.1, 1.0), 1.0);\n                target\n                    .draw(\n                        (\n                            &self.vertex_buffer,\n                            self.instance_buffer.per_instance().unwrap(),\n                        ),\n                        &self.index_buffer,\n                        &self.program,\n                        &glium::uniform! { matrix: view_proj },\n                        &params,\n                    )\n                    .unwrap();\n                target.finish().unwrap();\n            }\n            _ => (),\n        }\n    }\n\n    fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) {\n        if let Some(window) = self.window.as_ref() {\n            let bodies = match self.mode {\n                ExecutionMode::Par => self.benchmark.tick_par(),\n                ExecutionMode::ParReduce => self.benchmark.tick_par_reduce(),\n                ExecutionMode::Seq => self.benchmark.tick_seq(),\n            };\n\n            let mut mapping = self.instance_buffer.map();\n            for (body, instance) in bodies.iter().zip(mapping.iter_mut()) {\n                instance.world_position = [\n                    body.position.x as f32,\n                    body.position.y as f32,\n                    body.position.z as f32,\n                ];\n            }\n            window.request_redraw();\n        }\n    }\n}\n\npub fn visualize_benchmarks(num_bodies: usize, mode: ExecutionMode) {\n    let event_loop = EventLoop::new().unwrap();\n    let (window, display) = SimpleWindowBuilder::new()\n        .with_inner_size(800, 600)\n        .with_title(\"nbody demo\")\n        .build(&event_loop);\n\n    let benchmark = NBodyBenchmark::new(num_bodies, &mut rand::rng());\n\n    let vertex_shader_src = r#\"\n        #version 100\n\n        uniform mat4 matrix;\n\n        attribute vec3 position;\n        attribute vec3 world_position;\n        attribute vec3 color;\n\n        varying lowp vec3 v_color;\n\n        void main() {\n            v_color = color;\n            gl_Position = matrix * vec4(position * 0.1 + world_position * 0.0005, 1.0);\n        }\n    \"#;\n\n    let fragment_shader_src = r#\"\n        #version 100\n\n        varying lowp vec3 v_color;\n\n        void main() {\n            gl_FragColor = vec4(v_color, 1.0);\n        }\n    \"#;\n\n    let program =\n        Program::from_source(&display, vertex_shader_src, fragment_shader_src, None).unwrap();\n\n    let (vertices, indices) = icosahedron();\n    let vertex_buffer = VertexBuffer::new(&display, &vertices).unwrap();\n    let index_buffer = IndexBuffer::new(&display, PrimitiveType::TrianglesList, &indices).unwrap();\n\n    let mut rng = crate::seeded_rng();\n    let instances: Vec<_> = (0..num_bodies)\n        .map(|_| Instance {\n            color: [\n                rng.random_range(0.5..1.0),\n                rng.random_range(0.5..1.0),\n                rng.random_range(0.5..1.0),\n            ],\n            world_position: [0.0, 0.0, 0.0],\n        })\n        .collect();\n\n    let instance_buffer = VertexBuffer::dynamic(&display, &instances).unwrap();\n\n    let mut state = State {\n        window: Some(window),\n        mode,\n        instance_buffer,\n        benchmark,\n        display,\n        vertex_buffer,\n        index_buffer,\n        program,\n    };\n\n    let _ = event_loop.run_app(&mut state);\n}\n"
  },
  {
    "path": "rayon-demo/src/noop/mod.rs",
    "content": "const USAGE: &str = \"\nUsage: noop [--sleep N] [--iters N]\n\nNoop loop to measure CPU usage. See rayon-rs/rayon#642.\n\nOptions:\n    --sleep N       How long to sleep (in millis) between doing a spawn. [default: 10]\n    --iters N        Total time to execution (in millis). [default: 100]\n\";\n\nuse crate::cpu_time;\nuse docopt::Docopt;\n\n#[derive(serde::Deserialize)]\npub struct Args {\n    flag_sleep: u64,\n    flag_iters: u64,\n}\n\npub fn main(args: &[String]) {\n    let args: Args = Docopt::new(USAGE)\n        .and_then(|d| d.argv(args).deserialize())\n        .unwrap_or_else(|e| e.exit());\n\n    let m = cpu_time::measure_cpu(|| {\n        for _ in 1..args.flag_iters {\n            std::thread::sleep(std::time::Duration::from_millis(args.flag_sleep));\n            rayon::spawn(move || {});\n        }\n    });\n    println!(\n        \"noop --iters={} --sleep={}\",\n        args.flag_iters, args.flag_sleep\n    );\n    cpu_time::print_time(m);\n}\n"
  },
  {
    "path": "rayon-demo/src/pythagoras/mod.rs",
    "content": "//! How many Pythagorean triples exist less than or equal to a million?\n//! i.e. a²+b²=c² and a,b,c ≤ 1000000\n\nuse num::Integer;\nuse rayon::prelude::*;\nuse rayon::range::Iter;\nuse std::ops::Add;\n\n/// Use Euclid's formula to count Pythagorean triples\n///\n/// https://en.wikipedia.org/wiki/Pythagorean_triple#Generating_a_triple\n///\n/// For coprime integers m and n, with m > n and m-n is odd, then\n///     a = m²-n², b = 2mn, c = m²+n²\n///\n/// This is a coprime triple.  Multiplying by factors k covers all triples.\nfn par_euclid<FM, M, FN, N>(map_m: FM, map_n: FN) -> u32\nwhere\n    FM: FnOnce(Iter<u32>) -> M,\n    M: ParallelIterator<Item = u32>,\n    FN: Fn(Iter<u32>) -> N + Sync,\n    N: ParallelIterator<Item = u32>,\n{\n    map_m((1u32..2_000).into_par_iter())\n        .map(|m| -> u32 {\n            map_n((1..m).into_par_iter())\n                .filter(|n| (m - n).is_odd() && m.gcd(n) == 1)\n                .map(|n| 4_000_000 / (m * m + n * n))\n                .sum()\n        })\n        .sum()\n}\n\n/// Same as par_euclid, without tweaking split lengths\nfn par_euclid_weightless() -> u32 {\n    (1u32..2_000)\n        .into_par_iter()\n        .map(|m| -> u32 {\n            (1..m)\n                .into_par_iter()\n                .filter(|n| (m - n).is_odd() && m.gcd(n) == 1)\n                .map(|n| 4_000_000 / (m * m + n * n))\n                .sum()\n        })\n        .sum()\n}\n\n/// Same as par_euclid, without using rayon.\nfn euclid() -> u32 {\n    (1u32..2_000)\n        .map(|m| {\n            (1..m)\n                .filter(|n| (m - n).is_odd() && m.gcd(n) == 1)\n                .map(|n| 4_000_000 / (m * m + n * n))\n                .fold(0, Add::add)\n        })\n        .fold(0, Add::add)\n}\n\n#[bench]\n/// Benchmark without rayon at all\nfn euclid_serial(b: &mut test::Bencher) {\n    let count = euclid();\n    b.iter(|| assert_eq!(euclid(), count))\n}\n\n#[bench]\n/// Use huge minimums to force it fully serialized.\nfn euclid_faux_serial(b: &mut test::Bencher) {\n    let count = euclid();\n    let serial = |r: Iter<u32>| r.with_min_len(usize::MAX);\n    b.iter(|| assert_eq!(par_euclid(serial, serial), count))\n}\n\n#[bench]\n/// Use the default without any weights\nfn euclid_parallel_weightless(b: &mut test::Bencher) {\n    let count = euclid();\n    b.iter(|| assert_eq!(par_euclid_weightless(), count))\n}\n\n#[bench]\n/// Use the default settings.\nfn euclid_parallel_one(b: &mut test::Bencher) {\n    let count = euclid();\n    b.iter(|| assert_eq!(par_euclid(|m| m, |n| n), count))\n}\n\n#[bench]\n/// Use a low maximum to force the outer loop parallelized.\nfn euclid_parallel_outer(b: &mut test::Bencher) {\n    let count = euclid();\n    let parallel = |r: Iter<u32>| r.with_max_len(1);\n    b.iter(|| assert_eq!(par_euclid(parallel, |n| n), count))\n}\n\n#[bench]\n/// Use low maximums to force it fully parallelized.\nfn euclid_parallel_full(b: &mut test::Bencher) {\n    let count = euclid();\n    let parallel = |r: Iter<u32>| r.with_max_len(1);\n    b.iter(|| assert_eq!(par_euclid(parallel, parallel), count))\n}\n"
  },
  {
    "path": "rayon-demo/src/quicksort/bench.rs",
    "content": "use super::{Parallel, Sequential};\n\n// Size to use when doing `cargo bench`; extensively tuned to run in\n// \"not too long\" on my laptop -nmatsakis\nconst BENCH_SIZE: usize = 250_000_000 / 512;\n\nfn bench_harness<F: FnMut(&mut [u32])>(mut f: F, b: &mut test::Bencher) {\n    let base_vec = super::default_vec(BENCH_SIZE);\n    let mut sort_vec = base_vec.clone();\n    b.iter(|| {\n        sort_vec.clone_from(&base_vec);\n        f(&mut sort_vec);\n    });\n    assert!(super::is_sorted(&sort_vec));\n}\n\n#[bench]\nfn quick_sort_par_bench(b: &mut test::Bencher) {\n    bench_harness(super::quick_sort::<Parallel, u32>, b);\n}\n\n#[bench]\nfn quick_sort_seq_bench(b: &mut test::Bencher) {\n    bench_harness(super::quick_sort::<Sequential, u32>, b);\n}\n\n#[bench]\nfn quick_sort_splitter(b: &mut test::Bencher) {\n    use rayon::iter::ParallelIterator;\n\n    bench_harness(\n        |vec| {\n            ::rayon::iter::split(vec, |vec| {\n                if vec.len() > 1 {\n                    let mid = super::partition(vec);\n                    let (left, right) = vec.split_at_mut(mid);\n                    (left, Some(right))\n                } else {\n                    (vec, None)\n                }\n            })\n            .for_each(super::quick_sort::<Sequential, u32>)\n        },\n        b,\n    );\n}\n"
  },
  {
    "path": "rayon-demo/src/quicksort/mod.rs",
    "content": "#![allow(non_camel_case_types)]\n\nconst USAGE: &str = \"\nUsage: quicksort bench [options]\n       quicksort --help\n\nParallel quicksort. Only the main recursive step is parallelized.\n\nCommands:\n    bench              Run the benchmark in different modes and print the timings.\n\nOptions:\n    --size N           Number of 32-bit words to sort [default: 250000000] (1GB)\n    --par-only         Skip the sequential sort.\n    -h, --help         Show this message.\n\";\n\n#[derive(serde::Deserialize)]\npub struct Args {\n    cmd_bench: bool,\n    flag_size: usize,\n    flag_par_only: bool,\n}\n\nuse docopt::Docopt;\nuse rand::distr::StandardUniform;\nuse rand::Rng;\nuse std::time::Instant;\n\npub trait Joiner {\n    fn is_parallel() -> bool;\n    fn join<A, R_A, B, R_B>(oper_a: A, oper_b: B) -> (R_A, R_B)\n    where\n        A: FnOnce() -> R_A + Send,\n        B: FnOnce() -> R_B + Send,\n        R_A: Send,\n        R_B: Send;\n}\n\npub struct Parallel;\nimpl Joiner for Parallel {\n    #[inline]\n    fn is_parallel() -> bool {\n        true\n    }\n    #[inline]\n    fn join<A, R_A, B, R_B>(oper_a: A, oper_b: B) -> (R_A, R_B)\n    where\n        A: FnOnce() -> R_A + Send,\n        B: FnOnce() -> R_B + Send,\n        R_A: Send,\n        R_B: Send,\n    {\n        rayon::join(oper_a, oper_b)\n    }\n}\n\nstruct Sequential;\nimpl Joiner for Sequential {\n    #[inline]\n    fn is_parallel() -> bool {\n        false\n    }\n    #[inline]\n    fn join<A, R_A, B, R_B>(oper_a: A, oper_b: B) -> (R_A, R_B)\n    where\n        A: FnOnce() -> R_A + Send,\n        B: FnOnce() -> R_B + Send,\n        R_A: Send,\n        R_B: Send,\n    {\n        let a = oper_a();\n        let b = oper_b();\n        (a, b)\n    }\n}\n\npub fn quick_sort<J: Joiner, T: PartialOrd + Send>(v: &mut [T]) {\n    if v.len() <= 1 {\n        return;\n    }\n\n    if J::is_parallel() && v.len() <= 5 * 1024 {\n        return quick_sort::<Sequential, T>(v);\n    }\n\n    let mid = partition(v);\n    let (lo, hi) = v.split_at_mut(mid);\n    J::join(|| quick_sort::<J, T>(lo), || quick_sort::<J, T>(hi));\n}\n\nfn partition<T: PartialOrd + Send>(v: &mut [T]) -> usize {\n    let pivot = v.len() - 1;\n    let mut i = 0;\n    for j in 0..pivot {\n        if v[j] <= v[pivot] {\n            v.swap(i, j);\n            i += 1;\n        }\n    }\n    v.swap(i, pivot);\n    i\n}\n\npub fn is_sorted<T: Send + Ord>(v: &[T]) -> bool {\n    (1..v.len()).all(|i| v[i - 1] <= v[i])\n}\n\nfn default_vec(n: usize) -> Vec<u32> {\n    let rng = crate::seeded_rng();\n    rng.sample_iter(&StandardUniform).take(n).collect()\n}\n\nfn timed_sort<F: FnOnce(&mut [u32])>(n: usize, f: F, name: &str) -> u64 {\n    let mut v = default_vec(n);\n\n    let start = Instant::now();\n    f(&mut v[..]);\n    let dur = Instant::now() - start;\n    let nanos = u64::from(dur.subsec_nanos()) + dur.as_secs() * 1_000_000_000u64;\n    println!(\"{}: sorted {} ints: {} s\", name, n, nanos as f32 / 1e9f32);\n\n    // Check correctness\n    assert!(is_sorted(&v[..]));\n\n    nanos\n}\n\npub fn main(args: &[String]) {\n    let args: Args = Docopt::new(USAGE)\n        .and_then(|d| d.argv(args).deserialize())\n        .unwrap_or_else(|e| e.exit());\n\n    if args.cmd_bench {\n        if args.flag_par_only {\n            timed_sort(args.flag_size, quick_sort::<Parallel, u32>, \"par\");\n        } else {\n            let seq = timed_sort(args.flag_size, quick_sort::<Sequential, u32>, \"seq\");\n            let par = timed_sort(args.flag_size, quick_sort::<Parallel, u32>, \"par\");\n            let speedup = seq as f64 / par as f64;\n            println!(\"speedup: {speedup:.2}x\");\n        }\n    }\n}\n\n#[cfg(test)]\nmod bench;\n"
  },
  {
    "path": "rayon-demo/src/sieve/bench.rs",
    "content": "use super::NUM_PRIMES;\n\nconst MAGNITUDE: usize = 7;\n\nfn sieve_bench<TICK>(b: &mut test::Bencher, mut tick: TICK)\nwhere\n    TICK: FnMut(usize) -> Vec<bool>,\n{\n    let mut result = vec![];\n    b.iter(|| result = tick(super::max(MAGNITUDE)));\n    let num_primes = 1 + result.into_iter().filter(|&b| b).count();\n    assert_eq!(num_primes, NUM_PRIMES[MAGNITUDE]);\n}\n\n#[bench]\nfn sieve_serial(b: &mut ::test::Bencher) {\n    sieve_bench(b, super::sieve_serial);\n}\n\n#[bench]\nfn sieve_chunks(b: &mut ::test::Bencher) {\n    sieve_bench(b, super::sieve_chunks);\n}\n\n#[bench]\nfn sieve_parallel(b: &mut ::test::Bencher) {\n    sieve_bench(b, super::sieve_parallel);\n}\n"
  },
  {
    "path": "rayon-demo/src/sieve/mod.rs",
    "content": "const USAGE: &str = \"\nUsage: sieve bench\n       sieve --help\n\nSieve of Eratosthenes\n\nA sieve finds prime numbers by first assuming all candidates are prime,\nthen progressively using small primes to mark their multiples composite.\n\nNote that a given prime p only needs to start marking its multiples >=p²,\nas anything less will already have been marked by an even smaller prime\nfactor.  This also means that sieving up to N only requires primes up to\nsqrt(N) - a useful fact to prepare for parallel sieving.\n\nHere we have three forms of the sieve:\n\n- `sieve_serial`: direct iteration in serial\n- `sieve_chunks`: chunked iteration, still serial\n- `sieve_parallel`: chunked iteration in parallel\n\nThe performance improvement of `sieve_chunks` is largely due to cache\nlocality.  Since the sieve has to sweep repeatedly over the same memory,\nit's helpful that the chunk size can fit entirely in the CPU cache.  Then\n`sieve_parallel` also benefits from this as long as there's cache room for\nmultiple chunks, for the separate jobs in each thread.\n\nCommands:\n    bench              Run the benchmark in different modes and print the timings.\n\nOptions:\n    -h, --help         Show this message.\n\";\n\n#[derive(serde::Deserialize)]\npub struct Args {\n    cmd_bench: bool,\n}\n\n#[cfg(test)]\nmod bench;\n\nuse docopt::Docopt;\nuse rayon::prelude::*;\nuse std::time::{Duration, Instant};\n\nconst CHUNK_SIZE: usize = 100_000;\n\n// Number of Primes < 10^n\n// https://oeis.org/A006880\nconst NUM_PRIMES: &[usize] = &[\n    0,  // primes in 0..10^0\n    4,  // primes in 0..10^1\n    25, // etc\n    168,\n    1_229,\n    9_592,\n    78_498,\n    664_579,\n    5_761_455,\n    50_847_534,\n    455_052_511,\n    4_118_054_813,\n    37_607_912_018,\n    346_065_536_839,\n    3_204_941_750_802,\n    29_844_570_422_669,\n    279_238_341_033_925,\n    2_623_557_157_654_233,\n    24_739_954_287_740_860,\n    234_057_667_276_344_607,\n    2_220_819_602_560_918_840,\n];\n\n// For all of these sieves, sieve[i]==true -> 2*i+1 is prime\n\nfn max(magnitude: usize) -> usize {\n    10_usize.pow(magnitude as u32)\n}\n\n/// Sieve odd integers for primes < max.\nfn sieve_serial(max: usize) -> Vec<bool> {\n    let mut sieve = vec![true; max / 2];\n    sieve[0] = false; // 1 is not prime\n    for i in 1.. {\n        if sieve[i] {\n            let p = 2 * i + 1;\n            let pp = p * p;\n            if pp >= max {\n                break;\n            }\n            clear_stride(&mut sieve, pp / 2, p);\n        }\n    }\n    sieve\n}\n\n/// Sieve odd integers for primes < max using chunks.\nfn sieve_chunks(max: usize) -> Vec<bool> {\n    // first compute the small primes, up to sqrt(max).\n    let small_max = (max as f64).sqrt().ceil() as usize;\n    let mut sieve = sieve_serial(small_max);\n    sieve.resize(max / 2, true);\n\n    {\n        let (low, high) = sieve.split_at_mut(small_max / 2);\n        for (chunk_index, chunk) in high.chunks_mut(CHUNK_SIZE).enumerate() {\n            let i = small_max / 2 + chunk_index * CHUNK_SIZE;\n            let base = i * 2 + 1;\n            update_chunk(low, chunk, base);\n        }\n    }\n\n    sieve\n}\n\n/// Sieve odd integers for primes < max, in parallel!\nfn sieve_parallel(max: usize) -> Vec<bool> {\n    // first compute the small primes, up to sqrt(max).\n    let small_max = (max as f64).sqrt().ceil() as usize;\n    let mut sieve = sieve_serial(small_max);\n    sieve.resize(max / 2, true);\n\n    {\n        let (low, high) = sieve.split_at_mut(small_max / 2);\n        high.par_chunks_mut(CHUNK_SIZE)\n            .enumerate() // to figure out where this chunk came from\n            .with_max_len(1) // ensure every single chunk is a separate rayon job\n            .for_each(|(chunk_index, chunk)| {\n                let i = small_max / 2 + chunk_index * CHUNK_SIZE;\n                let base = i * 2 + 1;\n                update_chunk(low, chunk, base);\n            });\n    }\n\n    sieve\n}\n\n/// Update a chunk with low primes\nfn update_chunk(low: &[bool], chunk: &mut [bool], base: usize) {\n    let max = base + chunk.len() * 2;\n    for (i, &is_prime) in low.iter().enumerate() {\n        if is_prime {\n            let p = 2 * i + 1;\n            let pp = p * p;\n            if pp >= max {\n                break;\n            }\n\n            let pm = if pp < base {\n                // p² is too small - find the first odd multiple that's in range\n                (base.div_ceil(p) | 1) * p\n            } else {\n                pp\n            };\n\n            if pm < max {\n                clear_stride(chunk, (pm - base) / 2, p);\n            }\n        }\n    }\n}\n\nfn clear_stride(slice: &mut [bool], from: usize, stride: usize) {\n    slice[from..]\n        .iter_mut()\n        .step_by(stride)\n        .for_each(|x| *x = false)\n}\n\nfn measure(f: fn(usize) -> Vec<bool>) -> Duration {\n    const MAGNITUDE: usize = 9;\n\n    let start = Instant::now();\n    let sieve = f(max(MAGNITUDE));\n    let duration = start.elapsed();\n\n    // sanity check the number of primes found\n    let num_primes = 1 + sieve.into_iter().filter(|&b| b).count();\n    assert_eq!(num_primes, NUM_PRIMES[MAGNITUDE]);\n\n    duration\n}\n\npub fn main(args: &[String]) {\n    let args: Args = Docopt::new(USAGE)\n        .and_then(|d| d.argv(args).deserialize())\n        .unwrap_or_else(|e| e.exit());\n\n    if args.cmd_bench {\n        let serial = measure(sieve_serial).as_nanos();\n        println!(\"  serial: {serial:10} ns\");\n\n        let chunks = measure(sieve_chunks).as_nanos();\n        println!(\n            \"  chunks: {:10} ns -> {:.2}x speedup\",\n            chunks,\n            serial as f64 / chunks as f64\n        );\n\n        let parallel = measure(sieve_parallel).as_nanos();\n        println!(\n            \"parallel: {:10} ns -> {:.2}x speedup\",\n            parallel,\n            chunks as f64 / parallel as f64\n        );\n    }\n}\n"
  },
  {
    "path": "rayon-demo/src/sort.rs",
    "content": "use rand::distr::{Alphanumeric, StandardUniform, Uniform};\nuse rand::Rng;\nuse rayon::prelude::*;\nuse std::sync::atomic::AtomicUsize;\nuse std::sync::atomic::Ordering::SeqCst;\nuse test::{black_box, Bencher};\n\nfn gen_ascending(len: usize) -> Vec<u64> {\n    (0..len as u64).collect()\n}\n\nfn gen_descending(len: usize) -> Vec<u64> {\n    (0..len as u64).rev().collect()\n}\n\nfn gen_random(len: usize) -> Vec<u64> {\n    let rng = crate::seeded_rng();\n    rng.sample_iter(&StandardUniform).take(len).collect()\n}\n\nfn gen_mostly_ascending(len: usize) -> Vec<u64> {\n    let mut rng = crate::seeded_rng();\n    let len_dist = Uniform::new(0, len).unwrap();\n    let mut v = gen_ascending(len);\n    for _ in (0usize..).take_while(|x| x * x <= len) {\n        let x = rng.sample(len_dist);\n        let y = rng.sample(len_dist);\n        v.swap(x, y);\n    }\n    v\n}\n\nfn gen_mostly_descending(len: usize) -> Vec<u64> {\n    let mut rng = crate::seeded_rng();\n    let len_dist = Uniform::new(0, len).unwrap();\n    let mut v = gen_descending(len);\n    for _ in (0usize..).take_while(|x| x * x <= len) {\n        let x = rng.sample(len_dist);\n        let y = rng.sample(len_dist);\n        v.swap(x, y);\n    }\n    v\n}\n\nfn gen_strings(len: usize) -> Vec<String> {\n    let mut rng = crate::seeded_rng();\n    let rng = &mut rng;\n    let len_dist = Uniform::new(1, 21).unwrap();\n    let mut v = vec![];\n    for _ in 0..len {\n        let n = rng.sample(len_dist);\n        v.push(\n            rng.sample_iter(&Alphanumeric)\n                .map(char::from)\n                .take(n)\n                .collect(),\n        );\n    }\n    v\n}\n\nfn gen_big_random(len: usize) -> Vec<[u64; 16]> {\n    let rng = crate::seeded_rng();\n    rng.sample_iter(&StandardUniform)\n        .map(|x| [x; 16])\n        .take(len)\n        .collect()\n}\n\nmacro_rules! sort {\n    ($f:ident, $name:ident, $gen:expr, $len:expr) => {\n        #[bench]\n        fn $name(b: &mut Bencher) {\n            let v = $gen($len);\n            b.iter(|| v.clone().$f());\n            b.bytes = $len * size_of_val(&$gen(1)[0]) as u64;\n        }\n    };\n}\n\nmacro_rules! sort_keys {\n    ($f:ident, $name:ident, $gen:expr, $len:expr) => {\n        #[bench]\n        fn $name(b: &mut Bencher) {\n            let v = $gen($len);\n            b.iter(|| v.clone().$f(ToString::to_string));\n            b.bytes = $len * size_of_val(&$gen(1)[0]) as u64;\n        }\n    };\n}\n\nmacro_rules! sort_strings {\n    ($f:ident, $name:ident, $gen:expr, $len:expr) => {\n        #[bench]\n        fn $name(b: &mut Bencher) {\n            let v = $gen($len);\n            let v = v.iter().map(|s| &**s).collect::<Vec<&str>>();\n            b.iter(|| v.clone().$f());\n            b.bytes = $len * size_of::<&str>() as u64;\n        }\n    };\n}\n\nmacro_rules! sort_expensive {\n    ($f:ident, $name:ident, $gen:expr, $len:expr) => {\n        #[bench]\n        fn $name(b: &mut Bencher) {\n            let v = $gen($len);\n            b.iter(|| {\n                let count = AtomicUsize::new(0);\n                let mut v = v.clone();\n\n                v.$f(|a: &u64, b: &u64| {\n                    // This is an intentionally expensive comparison function: we have atomic\n                    // operations, landing pads due to a potential panic, a modulo operation, and\n                    // trigonometric functions.\n                    count.fetch_add(1, SeqCst);\n                    if count.load(SeqCst) % 1_000_000_000 == 0 {\n                        panic!(\"should not happen\");\n                    }\n                    (*a as f64).cos().partial_cmp(&(*b as f64).cos()).unwrap()\n                });\n\n                black_box(count);\n            });\n            b.bytes = $len * size_of_val(&$gen(1)[0]) as u64;\n        }\n    };\n}\n\nsort!(par_sort, par_sort_ascending, gen_ascending, 50_000);\nsort!(par_sort, par_sort_descending, gen_descending, 50_000);\nsort!(\n    par_sort,\n    par_sort_mostly_ascending,\n    gen_mostly_ascending,\n    50_000\n);\nsort!(\n    par_sort,\n    par_sort_mostly_descending,\n    gen_mostly_descending,\n    50_000\n);\nsort!(par_sort, par_sort_random, gen_random, 50_000);\nsort!(par_sort, par_sort_big, gen_big_random, 50_000);\nsort_strings!(par_sort, par_sort_strings, gen_strings, 50_000);\nsort_expensive!(par_sort_by, par_sort_expensive, gen_random, 50_000);\nsort_keys!(par_sort_by_key, par_sort_by_key, gen_random, 50_000);\nsort_keys!(\n    par_sort_by_cached_key,\n    par_sort_by_cached_key,\n    gen_random,\n    50_000\n);\n\nsort!(\n    par_sort_unstable,\n    par_sort_unstable_ascending,\n    gen_ascending,\n    50_000\n);\nsort!(\n    par_sort_unstable,\n    par_sort_unstable_descending,\n    gen_descending,\n    50_000\n);\nsort!(\n    par_sort_unstable,\n    par_sort_unstable_mostly_ascending,\n    gen_mostly_ascending,\n    50_000\n);\nsort!(\n    par_sort_unstable,\n    par_sort_unstable_mostly_descending,\n    gen_mostly_descending,\n    50_000\n);\nsort!(\n    par_sort_unstable,\n    par_sort_unstable_random,\n    gen_random,\n    50_000\n);\nsort!(\n    par_sort_unstable,\n    par_sort_unstable_big,\n    gen_big_random,\n    50_000\n);\nsort_strings!(\n    par_sort_unstable,\n    par_sort_unstable_strings,\n    gen_strings,\n    50_000\n);\nsort_expensive!(\n    par_sort_unstable_by,\n    par_sort_unstable_expensive,\n    gen_random,\n    50_000\n);\nsort_keys!(\n    par_sort_unstable_by_key,\n    par_sort_unstable_by_key,\n    gen_random,\n    50_000\n);\n\ntrait MergeSort {\n    fn demo_merge_sort(&mut self);\n}\n\nimpl<T: Ord + Send + Copy> MergeSort for [T] {\n    fn demo_merge_sort(&mut self) {\n        super::mergesort::merge_sort(self);\n    }\n}\n\nsort!(\n    demo_merge_sort,\n    demo_merge_sort_ascending,\n    gen_ascending,\n    50_000\n);\nsort!(\n    demo_merge_sort,\n    demo_merge_sort_descending,\n    gen_descending,\n    50_000\n);\nsort!(\n    demo_merge_sort,\n    demo_merge_sort_mostly_ascending,\n    gen_mostly_ascending,\n    50_000\n);\nsort!(\n    demo_merge_sort,\n    demo_merge_sort_mostly_descending,\n    gen_mostly_descending,\n    50_000\n);\nsort!(demo_merge_sort, demo_merge_sort_random, gen_random, 50_000);\nsort!(demo_merge_sort, demo_merge_sort_big, gen_big_random, 50_000);\nsort_strings!(\n    demo_merge_sort,\n    demo_merge_sort_strings,\n    gen_strings,\n    50_000\n);\n//sort_expensive!(demo_merge_sort_by, demo_merge_sort_expensive, gen_random, 50_000);\n\ntrait QuickSort {\n    fn demo_quick_sort(&mut self);\n}\n\nimpl<T: PartialOrd + Send> QuickSort for [T] {\n    fn demo_quick_sort(&mut self) {\n        use crate::quicksort::{quick_sort, Parallel};\n        quick_sort::<Parallel, T>(self);\n    }\n}\n\n// ascending/descending sorts need better pivot choices to avoid stack overflow\n//sort!(demo_quick_sort, demo_quick_sort_ascending, gen_ascending, 50_000);\n//sort!(demo_quick_sort, demo_quick_sort_descending, gen_descending, 50_000);\nsort!(\n    demo_quick_sort,\n    demo_quick_sort_mostly_ascending,\n    gen_mostly_ascending,\n    50_000\n);\nsort!(\n    demo_quick_sort,\n    demo_quick_sort_mostly_descending,\n    gen_mostly_descending,\n    50_000\n);\nsort!(demo_quick_sort, demo_quick_sort_random, gen_random, 50_000);\nsort!(demo_quick_sort, demo_quick_sort_big, gen_big_random, 50_000);\nsort_strings!(\n    demo_quick_sort,\n    demo_quick_sort_strings,\n    gen_strings,\n    50_000\n);\n//sort_expensive!(demo_quick_sort_by, demo_quick_sort_expensive, gen_random, 50_000);\n"
  },
  {
    "path": "rayon-demo/src/str_split.rs",
    "content": "//! Some microbenchmarks for splitting strings\n\nuse rand::seq::SliceRandom;\nuse rayon::prelude::*;\nuse std::sync::LazyLock;\nuse test::Bencher;\n\nstatic HAYSTACK: LazyLock<String> = LazyLock::new(|| {\n    let mut rng = crate::seeded_rng();\n    let mut bytes: Vec<u8> = \"abcdefg \".bytes().cycle().take(1_000_000).collect();\n    bytes.shuffle(&mut rng);\n    String::from_utf8(bytes).unwrap()\n});\n\nstatic COUNT: LazyLock<usize> = LazyLock::new(|| HAYSTACK.split(' ').count());\n\n// Try multiple kinds of whitespace, but HAYSTACK only contains plain spaces.\nconst WHITESPACE: &[char] = &['\\r', '\\n', ' ', '\\t'];\n\nfn get_string_count() -> (&'static str, usize) {\n    (&HAYSTACK, *COUNT)\n}\n\n#[bench]\nfn parallel_space_char(b: &mut Bencher) {\n    let (string, count) = get_string_count();\n    b.iter(|| assert_eq!(string.par_split(' ').count(), count))\n}\n\n#[bench]\nfn parallel_space_chars(b: &mut Bencher) {\n    let (string, count) = get_string_count();\n    b.iter(|| assert_eq!(string.par_split(WHITESPACE).count(), count))\n}\n\n#[bench]\nfn parallel_space_fn(b: &mut Bencher) {\n    let (string, count) = get_string_count();\n    b.iter(|| assert_eq!(string.par_split(|c| c == ' ').count(), count))\n}\n\n#[bench]\nfn serial_space_char(b: &mut Bencher) {\n    let (string, count) = get_string_count();\n    b.iter(|| assert_eq!(string.split(' ').count(), count))\n}\n\n#[bench]\nfn serial_space_chars(b: &mut Bencher) {\n    let (string, count) = get_string_count();\n    b.iter(|| assert_eq!(string.split(WHITESPACE).count(), count))\n}\n\n#[bench]\n#[expect(clippy::manual_pattern_char_comparison)]\nfn serial_space_fn(b: &mut Bencher) {\n    let (string, count) = get_string_count();\n    b.iter(|| assert_eq!(string.split(|c| c == ' ').count(), count))\n}\n\n#[bench]\nfn serial_space_str(b: &mut Bencher) {\n    let (string, count) = get_string_count();\n    #[allow(clippy::single_char_pattern)]\n    b.iter(|| assert_eq!(string.split(\" \").count(), count))\n}\n"
  },
  {
    "path": "rayon-demo/src/tree.rs",
    "content": "//! Some benches for tree walks.\nuse rayon::prelude::*;\n\nconst SIZE: u64 = 100_000;\nconst VAL: u64 = SIZE * (SIZE - 1) / 2;\n\n#[bench]\nfn tree_prefix_collect(b: &mut ::test::Bencher) {\n    let mut vec = None;\n    b.iter(|| {\n        vec = Some(\n            rayon::iter::walk_tree_prefix(0u64..SIZE, |r| {\n                // root is smallest\n                let mid = (r.start + 1 + r.end) / 2;\n                // small indices to the left, large to the right\n                std::iter::once((r.start + 1)..mid)\n                    .chain(std::iter::once(mid..r.end))\n                    .filter(|r| !r.is_empty())\n            })\n            .map(|r| r.start)\n            .collect::<Vec<_>>(),\n        )\n    });\n    assert!(vec.unwrap().into_iter().eq(0..SIZE));\n}\n\n#[bench]\nfn tree_postfix_collect(b: &mut ::test::Bencher) {\n    let mut vec = None;\n    b.iter(|| {\n        vec = Some(\n            rayon::iter::walk_tree_postfix(0u64..SIZE, |r| {\n                // root is largest\n                let mid = (r.start + r.end - 1) / 2;\n                // small indices to the left, large to the right\n                std::iter::once(r.start..mid)\n                    .chain(std::iter::once(mid..(r.end - 1)))\n                    .filter(|r| !r.is_empty())\n            })\n            .map(|r| r.end - 1)\n            .collect::<Vec<_>>(),\n        )\n    });\n    assert!(vec.unwrap().into_iter().eq(0..SIZE));\n}\n\n#[bench]\nfn tree_prefix_sum(b: &mut ::test::Bencher) {\n    b.iter(|| {\n        let s = rayon::iter::walk_tree_prefix(0u64..SIZE, |r| {\n            // root is smallest\n            let mid = (r.start + 1 + r.end) / 2;\n            // small indices to the left, large to the right\n            std::iter::once((r.start + 1)..mid)\n                .chain(std::iter::once(mid..r.end))\n                .filter(|r| !r.is_empty())\n        })\n        .map(|r| r.start)\n        .sum::<u64>();\n        assert_eq!(s, VAL)\n    })\n}\n\n#[bench]\nfn tree_postfix_sum(b: &mut ::test::Bencher) {\n    b.iter(|| {\n        let s = rayon::iter::walk_tree_postfix(0u64..SIZE, |r| {\n            // root is smallest\n            let mid = (r.start + 1 + r.end) / 2;\n            // small indices to the left, large to the right\n            std::iter::once((r.start + 1)..mid)\n                .chain(std::iter::once(mid..r.end))\n                .filter(|r| !r.is_empty())\n        })\n        .map(|r| r.start)\n        .sum::<u64>();\n        assert_eq!(s, VAL)\n    })\n}\n"
  },
  {
    "path": "rayon-demo/src/tsp/bench.rs",
    "content": "use std::path::Path;\n\nuse super::graph::Node;\nuse super::parse_solver;\nuse super::solver::SolverCx;\n\nfn run_dir(\n    b: &mut test::Bencher,\n    name: &str,\n    seq_threshold: usize,\n    exp_weight: usize,\n    exp_path: Vec<usize>,\n) {\n    let manifest_dir = Path::new(env!(\"CARGO_MANIFEST_DIR\"));\n    let tsp_path = manifest_dir.join(\"data/tsp/\").join(name);\n    let graph = parse_solver(&tsp_path).unwrap();\n    let mut solution = None;\n    b.iter(|| {\n        let mut solver = SolverCx::new(&graph, seq_threshold);\n        solver.search_from(Node::new(0));\n        solution = Some(solver.into_result());\n    });\n    let (path, weight) = solution.unwrap();\n    let mut path: Vec<usize> = path.unwrap().iter().map(|n| n.index()).collect();\n    if path.iter().rev().lt(&path) {\n        path.reverse(); // normalize the direction\n    }\n    assert_eq!(\n        exp_weight,\n        weight.to_usize(),\n        \"actual weight ({weight:?}) did not match expectation ({exp_weight:?})\"\n    );\n    assert_eq!(\n        exp_path, path,\n        \"best path ({path:?}) did not match expectation ({exp_path:?})\"\n    );\n}\n\n#[bench]\nfn dj10(b: &mut test::Bencher) {\n    // these numbers are tuned to \"not take THAT long\" in cargo bench,\n    // basically, but still exercise the spawning stuff -- each run\n    // should spawn 6! (720) tasks or so this way.\n    run_dir(\n        b,\n        \"dj10.tsp\",\n        4,\n        2577,\n        vec![0, 1, 3, 2, 4, 6, 8, 7, 5, 9, 0],\n    );\n}\n"
  },
  {
    "path": "rayon-demo/src/tsp/graph.rs",
    "content": "use fixedbitset::FixedBitSet;\nuse std::iter;\n\nuse super::weight::Weight;\n\npub struct Graph {\n    num_nodes: usize,\n\n    // a 2-d matrix indexed by (source, target); if `Weight::max()`\n    // is stored in a particular entry, that means that there is no\n    // edge. Otherwise, the weight is found.\n    weights: Vec<Weight>,\n}\n\nimpl Graph {\n    pub fn new(num_nodes: usize) -> Graph {\n        Graph {\n            num_nodes,\n            weights: iter::repeat(Weight::max())\n                .take(num_nodes * num_nodes)\n                .collect(),\n        }\n    }\n\n    pub fn num_nodes(&self) -> usize {\n        self.num_nodes\n    }\n\n    pub fn all_nodes(&self) -> impl Iterator<Item = Node> {\n        (0..self.num_nodes).map(Node::new)\n    }\n\n    pub fn node_set(&self) -> NodeSet {\n        NodeSet {\n            bits: FixedBitSet::with_capacity(self.num_nodes),\n        }\n    }\n\n    fn edge_index(&self, source: Node, target: Node) -> usize {\n        (source.index * self.num_nodes) + target.index\n    }\n\n    pub fn set_weight(&mut self, source: Node, target: Node, w: Weight) {\n        assert!(!w.is_max());\n        let index = self.edge_index(source, target);\n        self.weights[index] = w;\n    }\n\n    pub fn edge_weight(&self, source: Node, target: Node) -> Option<Weight> {\n        let w = self.weights[self.edge_index(source, target)];\n        if w.is_max() {\n            None\n        } else {\n            Some(w)\n        }\n    }\n\n    pub fn edges(&self, source: Node) -> impl Iterator<Item = Edge> + '_ {\n        self.all_nodes().filter_map(move |target| {\n            self.edge_weight(source, target).map(|weight| Edge {\n                source,\n                target,\n                weight,\n            })\n        })\n    }\n}\n\n#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]\npub struct Node {\n    index: usize,\n}\n\nimpl Node {\n    pub fn new(index: usize) -> Node {\n        Node { index }\n    }\n\n    pub fn index(self) -> usize {\n        self.index\n    }\n}\n\n#[derive(Debug, PartialEq, Eq)]\npub struct Edge {\n    pub source: Node,\n    pub target: Node,\n    pub weight: Weight,\n}\n\n#[derive(Clone, Debug)]\npub struct NodeSet {\n    bits: FixedBitSet,\n}\n\nimpl NodeSet {\n    pub fn contains(&self, node: Node) -> bool {\n        self.bits.contains(node.index)\n    }\n\n    pub fn with(&self, node: Node) -> NodeSet {\n        let mut s = self.clone();\n        s.insert(node);\n        s\n    }\n\n    pub fn insert(&mut self, node: Node) {\n        self.bits.insert(node.index);\n    }\n\n    pub fn remove(&mut self, node: Node) {\n        self.bits.remove(node.index);\n    }\n}\n"
  },
  {
    "path": "rayon-demo/src/tsp/mod.rs",
    "content": "//! A solver for the Travelling Salesman Problem.\n//!\n//! Based on code developed at ETH by Christoph von Praun, Florian\n//! Schneider, Nicholas Matsakis, and Thomas Gross.\n\nuse docopt::Docopt;\nuse std::error::Error;\nuse std::fmt::Write;\nuse std::fs::File;\nuse std::io::prelude::*;\nuse std::path::Path;\nuse std::time::Instant;\n\n#[cfg(test)]\nmod bench;\nmod graph;\nmod parser;\nmod solver;\nmod step;\nmod tour;\nmod weight;\n\nuse self::graph::{Graph, Node};\nuse self::solver::SolverCx;\n\nconst USAGE: &str = \"\nUsage: tsp bench [--seq-threshold N] [--from N] <datafile>\n\nParallel traveling salesman problem solver. Data input is expected to\nbe in TSPLIB format.\n\nSuggested command:\n    cargo run --release -- tsp bench data/tsp/dj15.tsp --seq-threshold 8\n\nCommands:\n    bench              Run the benchmark and print the timings.\n\nOptions:\n    -h, --help         Show this message.\n    --seq-threshold N  Adjust sequential fallback threshold [default: 10].\n                       Fall back to seq search when there are N or fewer nodes remaining.\n                       Lower values of N mean more parallelism.\n    --from N           Node index from which to start the search [default: 0].\n\";\n\n#[derive(serde::Deserialize)]\npub struct Args {\n    cmd_bench: bool,\n    arg_datafile: String,\n    flag_seq_threshold: usize,\n    flag_from: usize,\n}\n\npub fn main(args: &[String]) {\n    let args: Args = Docopt::new(USAGE)\n        .and_then(|d| d.argv(args).deserialize())\n        .unwrap_or_else(|e| e.exit());\n\n    if args.cmd_bench {\n        let _ = run_solver(\n            Path::new(&args.arg_datafile),\n            args.flag_seq_threshold,\n            args.flag_from,\n        );\n    }\n}\n\nfn run_solver(datafile: &Path, seq_threshold: usize, from: usize) -> Result<(), ()> {\n    let graph = match parse_solver(datafile) {\n        Ok(g) => g,\n        Err(e) => {\n            println!(\"failed to parse `{}`: {}\", datafile.display(), e);\n            return Err(());\n        }\n    };\n\n    println!(\"Graph size   : {} nodes.\", graph.num_nodes());\n    println!(\"Seq threshold: {seq_threshold} nodes.\");\n\n    if from >= graph.num_nodes() {\n        println!(\"Invalid node index given for `--from`: {from}\");\n        return Err(());\n    }\n\n    let mut solver = SolverCx::new(&graph, seq_threshold);\n    let par_start = Instant::now();\n    solver.search_from(Node::new(from));\n    let par_time = par_start.elapsed();\n\n    let (path, weight) = solver.into_result();\n\n    println!(\"Total search time: {par_time:?}\");\n    if let Some(path) = path {\n        println!(\"Cheapest path cost: {}\", weight.to_usize());\n        let mut output = \"Cheapest path:\".to_string();\n        for node in path {\n            let _ = write!(output, \" {}\", node.index());\n        }\n        println!(\"{output}\");\n    } else {\n        println!(\"No path found.\");\n    }\n\n    Ok(())\n}\n\nfn parse_solver(datafile: &Path) -> Result<Graph, Box<dyn Error>> {\n    let mut file = File::open(datafile)?;\n    let mut text = String::new();\n    file.read_to_string(&mut text)?;\n    let graph = parser::parse_tsp_data(&text)?;\n    Ok(graph)\n}\n"
  },
  {
    "path": "rayon-demo/src/tsp/parser.rs",
    "content": "use regex::Regex;\nuse std::collections::HashMap;\nuse std::str::{FromStr, Lines};\nuse std::sync::LazyLock;\n\nuse super::graph::{Graph, Node};\nuse super::weight::Weight;\n\n// Parses \"TSPLIB\" files from sources like\n//\n// https://www.math.uwaterloo.ca/tsp/world/dj38.tsp\n//\n// The format looks roughly like this, at least for EUC_2D cases:\n//\n// NAME: dj38\n// COMMENT : 38 locations in Djibouti\n// COMMENT : Derived from National Imagery and Mapping Agency data\n// COMMENT : This file is a corrected version of dj89, where duplications\n// COMMENT:  have been removed.  Thanks to Jay Muthuswamy and others for\n// COMMENT:  requesting data sets without duplications.\n// TYPE: TSP\n// DIMENSION: 38\n// EDGE_WEIGHT_TYPE: EUC_2D\n// NODE_COORD_SECTION\n// 1 11003.611100 42102.500000\n\nstatic HEADER: LazyLock<Regex> = LazyLock::new(|| Regex::new(r\"([A-Z_]+)\\s*:(.*)\").unwrap());\n\nstatic COORD: LazyLock<Regex> =\n    LazyLock::new(|| Regex::new(r\"([0-9]+) ([0-9.]+) ([0-9.]+)\").unwrap());\n\npub fn parse_tsp_data(text: &str) -> Result<Graph, String> {\n    let mut data = Data::new(text);\n    let mut num_nodes = None;\n\n    while let Some(header) = parse_tsp_header(&mut data) {\n        match header.name {\n            \"NAME\" => {}\n            \"COMMENT\" => {}\n            \"TYPE\" => {\n                if header.value != \"TSP\" {\n                    return Err(format!(\n                        \"line {}: expected \\\"TSP\\\" for TYPE, not {:?}\",\n                        header.line, header.value\n                    ));\n                }\n            }\n            \"DIMENSION\" => match usize::from_str(header.value) {\n                Ok(n) => num_nodes = Some(n),\n                Err(_) => {\n                    return Err(format!(\n                        \"line {}: expected an integer for DIMENSION, not {:?}\",\n                        header.line, header.value\n                    ));\n                }\n            },\n            \"EDGE_WEIGHT_TYPE\" => {\n                if header.value != \"EUC_2D\" {\n                    return Err(format!(\n                        \"line {}: expected \\\"EUC_2D\\\" for EDGE_WEIGHT_TYPE, not \\\n                         {:?}\",\n                        header.line, header.value\n                    ));\n                }\n            }\n            _ => {\n                return Err(format!(\n                    \"line {}: unknown header type {}\",\n                    header.line, header.name\n                ));\n            }\n        }\n    }\n\n    let num_nodes = match num_nodes {\n        Some(n) => n,\n        None => {\n            return Err(format!(\n                \"line {}: never found DIMENSION header\",\n                data.line_num\n            ));\n        }\n    };\n    let mut graph = Graph::new(num_nodes);\n\n    if parse_coord_header(&mut data).is_none() {\n        return Err(format!(\n            \"line {}: expected NODE_COORD_SECTION\",\n            data.line_num\n        ));\n    }\n\n    let mut coords = HashMap::new();\n    while let Some((node, x, y)) = parse_coord(&mut data) {\n        coords.insert(node, (x, y));\n    }\n\n    for i in graph.all_nodes() {\n        let coord_i = match coords.get(&i) {\n            Some(v) => v,\n            None => {\n                return Err(format!(\n                    \"line {}: never found coordinate for node {}\",\n                    data.line_num,\n                    i.index()\n                ));\n            }\n        };\n        for j in graph.all_nodes().filter(|&j| j != i) {\n            let coord_j = match coords.get(&j) {\n                Some(v) => v,\n                None => {\n                    return Err(format!(\n                        \"line {}: never found coordinate for node {}\",\n                        data.line_num,\n                        j.index()\n                    ));\n                }\n            };\n\n            // \"For these instances, the cost of travel between cities\n            // is specified by the Eulidean distance rounded to the\n            // nearest whole number (the TSPLIB EUC_2D-norm).\"\n            let distance = (coord_i.0 - coord_j.0).powi(2) + (coord_i.1 - coord_j.1).powi(2);\n            let distance = distance.sqrt();\n            let distance = distance.round();\n            let weight = Weight::new(distance as usize);\n            graph.set_weight(i, j, weight);\n        }\n    }\n\n    while let Some(()) = parse_blank(&mut data) {}\n\n    if data.current_line.is_some() {\n        return Err(format!(\"line {}: expected EOF\", data.line_num));\n    }\n\n    Ok(graph)\n}\n\npub struct Data<'text> {\n    current_line: Option<&'text str>,\n    line_num: usize,\n    next_lines: Lines<'text>,\n}\n\nimpl<'text> Data<'text> {\n    pub fn new(data: &'text str) -> Data<'text> {\n        let mut lines = data.lines();\n        let current_line = lines.next();\n        Data {\n            current_line,\n            line_num: 1,\n            next_lines: lines,\n        }\n    }\n\n    pub fn advance(&mut self) {\n        self.current_line = self.next_lines.next();\n        self.line_num += 1;\n    }\n}\n\npub struct Header<'text> {\n    line: usize,\n    name: &'text str,\n    value: &'text str,\n}\n\npub fn parse_tsp_header<'text>(data: &mut Data<'text>) -> Option<Header<'text>> {\n    data.current_line.and_then(|current_line| {\n        HEADER.captures(current_line).map(|captures| {\n            data.advance();\n            Header {\n                line: data.line_num - 1,\n                name: captures.get(1).unwrap().as_str().trim(),\n                value: captures.get(2).unwrap().as_str().trim(),\n            }\n        })\n    })\n}\n\npub fn parse_coord_header(data: &mut Data<'_>) -> Option<()> {\n    data.current_line.and_then(|current_line| {\n        if current_line == \"NODE_COORD_SECTION\" {\n            data.advance();\n            Some(())\n        } else {\n            None\n        }\n    })\n}\n\npub fn parse_coord(data: &mut Data<'_>) -> Option<(Node, f64, f64)> {\n    // 1 11003.611100 42102.500000\n    data.current_line.and_then(|current_line| {\n        COORD.captures(current_line).and_then(|captures| {\n            usize::from_str(captures.get(1).unwrap().as_str())\n                .ok()\n                .and_then(|n| {\n                    f64::from_str(captures.get(2).unwrap().as_str())\n                        .ok()\n                        .and_then(|x| {\n                            f64::from_str(captures.get(3).unwrap().as_str())\n                                .ok()\n                                .and_then(|y| {\n                                    if n > 0 {\n                                        data.advance();\n                                        Some((Node::new(n - 1), x, y))\n                                    } else {\n                                        None\n                                    }\n                                })\n                        })\n                })\n        })\n    })\n}\n\npub fn parse_blank(data: &mut Data<'_>) -> Option<()> {\n    data.current_line.and_then(|current_line| {\n        if current_line.trim().is_empty() {\n            data.advance();\n            Some(())\n        } else {\n            None\n        }\n    })\n}\n"
  },
  {
    "path": "rayon-demo/src/tsp/solver.rs",
    "content": "use std::collections::BinaryHeap;\nuse std::sync::atomic::{AtomicUsize, Ordering};\nuse std::sync::{Arc, Mutex};\n\nuse super::graph::{Graph, Node};\nuse super::step;\nuse super::tour::TourPrefix;\nuse super::weight::Weight;\n\n/// Shared context\npub struct SolverCx<'s> {\n    graph: &'s Graph,\n    seq_threshold: usize,\n    priority_queue: Mutex<BinaryHeap<Arc<TourPrefix>>>,\n    tour_counter: AtomicUsize,\n    min_tour_weight: AtomicUsize,\n    min_tour: Mutex<Option<Vec<Node>>>,\n}\n\n/// Just an opaque integer assigned to each tour element as we go;\n/// lets us give them an ordering independent from the lower bound.\n#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]\npub struct TourId {\n    id: usize,\n}\n\nimpl<'s> SolverCx<'s> {\n    pub fn new(graph: &'s Graph, seq_threshold: usize) -> Self {\n        SolverCx {\n            graph,\n            seq_threshold,\n            priority_queue: Mutex::new(BinaryHeap::new()),\n            tour_counter: AtomicUsize::new(0),\n            min_tour_weight: AtomicUsize::new(usize::MAX),\n            min_tour: Mutex::new(None),\n        }\n    }\n\n    pub fn search_from(&mut self, node: Node) {\n        // Enqueue the initial prefix:\n        let id = self.tour_id();\n        let mut visited = self.graph.node_set();\n        visited.insert(node);\n        self.priority_queue\n            .get_mut()\n            .unwrap()\n            .push(Arc::new(TourPrefix {\n                id,\n                node,\n                len: 1,\n                prefix_weight: Weight::zero(),\n                priority: Weight::max().to_priority(),\n                visited,\n                previous: None,\n            }));\n\n        // Start the iteration:\n        rayon::scope(|s| step::step(s, self));\n    }\n\n    pub fn seq_threshold(&self) -> usize {\n        self.seq_threshold\n    }\n\n    pub fn tour_id(&self) -> TourId {\n        let counter = self.tour_counter.fetch_add(1, Ordering::Relaxed);\n        TourId { id: counter }\n    }\n\n    pub fn graph(&self) -> &'s Graph {\n        self.graph\n    }\n\n    pub fn enqueue(&self, tour_element: Arc<TourPrefix>) {\n        let mut priority_queue = self.priority_queue.lock().unwrap();\n        priority_queue.push(tour_element);\n    }\n\n    pub fn dequeue(&self) -> Option<Arc<TourPrefix>> {\n        let mut priority_queue = self.priority_queue.lock().unwrap();\n        priority_queue.pop()\n    }\n\n    pub fn min_tour_weight(&self) -> Weight {\n        // Relaxed read is ok because the only time we *care* about\n        // this being precise, we are holding `min_tour` lock; and\n        // that is also the only time we write to it. This is subtle.\n        Weight::new(self.min_tour_weight.load(Ordering::Relaxed))\n    }\n\n    pub fn add_complete_tour(&self, tour: &[Node], weight: Weight) {\n        if weight < self.min_tour_weight() {\n            let mut min_tour = self.min_tour.lock().unwrap();\n            if min_tour.is_none() || weight < self.min_tour_weight() {\n                // this is a new minimum!\n                *min_tour = Some(tour.to_vec());\n                self.min_tour_weight\n                    .store(weight.to_usize(), Ordering::Relaxed);\n            }\n        }\n    }\n\n    pub fn into_result(self) -> (Option<Vec<Node>>, Weight) {\n        let weight = self.min_tour_weight();\n        (self.min_tour.into_inner().unwrap(), weight)\n    }\n}\n"
  },
  {
    "path": "rayon-demo/src/tsp/step.rs",
    "content": "use rayon::Scope;\nuse std::sync::Arc;\n\nuse super::graph::{Graph, Node, NodeSet};\nuse super::solver::SolverCx;\nuse super::tour::TourPrefix;\nuse super::weight::Weight;\n\npub fn step<'s>(scope: &Scope<'s>, solver: &'s SolverCx<'s>) {\n    let element = solver.dequeue().unwrap();\n\n    let remaining = solver.graph().num_nodes() - element.len;\n    if remaining <= solver.seq_threshold() {\n        solve_tour_seq(solver, element);\n    } else {\n        split_tour(scope, solver, element);\n    }\n}\n\nfn split_tour<'s>(scope: &Scope<'s>, solver: &'s SolverCx<'s>, element: Arc<TourPrefix>) {\n    let graph = solver.graph();\n    let last_node = element.node;\n    for next_edge in graph.edges(last_node) {\n        // for each place we could go next...\n        let next_node = next_edge.target;\n        if !element.visited(next_node) {\n            // ...check we haven't already been there...\n            let weight = next_edge.weight;\n            if (element.prefix_weight + weight) < solver.min_tour_weight() {\n                // ...and that we haven't already found a cheaper route\n                let visited = element.visited.with(next_node);\n\n                let prefix_weight = element.prefix_weight + weight;\n\n                let next_lower_bound =\n                    compute_lower_bound(solver.graph(), &element.visited, &visited, prefix_weight);\n\n                let next_tour = Arc::new(TourPrefix {\n                    id: solver.tour_id(),\n                    priority: next_lower_bound.to_priority(),\n                    node: next_node,\n                    len: element.len + 1,\n                    prefix_weight,\n                    visited,\n                    previous: Some(element.clone()),\n                });\n                solver.enqueue(next_tour);\n                scope.spawn(move |s| step(s, solver));\n            }\n        }\n    }\n}\n\n/// Compute a lower bound for completing the tour, given that we have\n/// a partial tour which visits the nodes in `visited` at the cost of\n/// `weight`. There are a number of ways you could to this; this one\n/// is intended to be a general method. We look at each node that is\n/// not yet visited and find the cheapest incoming edge and sum those\n/// up.  The idea is that we must *somehow* get to each of those nodes.\nfn compute_lower_bound(\n    graph: &Graph,\n    prev_visited: &NodeSet,\n    visited: &NodeSet,\n    weight: Weight,\n) -> Weight {\n    // Our path looks like this\n    //\n    //     START ~> n0 ... nJ ~> nK ~> ... nZ -> START\n    //     ------------------    --    ---------------\n    //     prev_visited       next_node     the future\n    //\n    // We want to find all edges that are targeting \"the future\"\n    // from a node that is *not* in `prev_visited`.\n\n    let mut min_weights: Vec<_> = graph\n        .all_nodes()\n        .map(|i| {\n            if visited.contains(i) {\n                Weight::zero()\n            } else {\n                Weight::max()\n            }\n        })\n        .collect();\n\n    for i in graph.all_nodes().filter(|&i| !prev_visited.contains(i)) {\n        for j in graph.all_nodes().filter(|&j| !visited.contains(j)) {\n            if let Some(w) = graph.edge_weight(i, j) {\n                // track the cheapest way to reach node `j` that doesn't\n                // start from one of the nodes we've been to already (but\n                // maybe starts from the most recent node):\n                min_weights[j.index()] = Ord::min(w, min_weights[j.index()]);\n            }\n        }\n    }\n\n    min_weights.iter().fold(Weight::zero(), |w1, &w2| w1 + w2) + weight\n}\n\nfn solve_tour_seq(solver: &SolverCx<'_>, element: Arc<TourPrefix>) {\n    // Sequentially enumerate all possible tours starting from this point.\n    let graph = solver.graph();\n    let mut path = Vec::with_capacity(graph.num_nodes() + 1);\n    let mut visited = element.visited.clone();\n\n    // unwind the current prefix into `path`; the path is stored in\n    // reverse order, so we have to reverse at the end. i.e., if the\n    // path were N0, N1, N2, we would have:\n    //\n    //     N2 -> N1 -> N0\n    let mut p = &element;\n    loop {\n        path.push(p.node);\n        if let Some(ref n) = p.previous {\n            p = n;\n        } else {\n            break;\n        }\n    }\n    path.reverse();\n\n    if path.len() == graph.num_nodes() {\n        complete_tour(solver, &mut path, element.prefix_weight);\n    } else {\n        enumerate_sequentially(solver, &mut path, &mut visited, element.prefix_weight);\n    }\n}\n\nfn enumerate_sequentially(\n    solver: &SolverCx<'_>,\n    path: &mut Vec<Node>,\n    visited: &mut NodeSet,\n    mut weight: Weight,\n) {\n    // Try to figure out what node to visit next.\n    let graph = solver.graph();\n    let prev = *path.last().unwrap();\n    for i in graph.all_nodes() {\n        // Don't go back places we've already been.\n        if visited.contains(i) {\n            continue;\n        }\n\n        // Not connected to previous node.\n        let edge_weight = match graph.edge_weight(prev, i) {\n            Some(w) => w,\n            None => continue,\n        };\n\n        // Check if this is better than cheapest found by anybody else so far.\n        if weight + edge_weight > solver.min_tour_weight() {\n            continue;\n        }\n\n        // Commit to `i` as the next node for us to visit.\n        weight += edge_weight;\n        path.push(i);\n        visited.insert(i);\n\n        if path.len() < graph.num_nodes() {\n            // Not yet completed the whole graph, keep looking.\n            enumerate_sequentially(solver, path, visited, weight);\n        } else {\n            // Completed the whole graph; we have to get back to the start node now (if we can).\n            complete_tour(solver, path, weight);\n        }\n\n        // Uncommit to `i`.\n        weight -= edge_weight;\n        path.pop();\n        visited.remove(i);\n    }\n}\n\nfn complete_tour(solver: &SolverCx<'_>, path: &mut Vec<Node>, weight: Weight) {\n    let graph = solver.graph();\n    debug_assert!(path.len() == graph.num_nodes());\n    let home = path[0];\n    let last = *path.last().unwrap();\n    if let Some(home_weight) = graph.edge_weight(last, home) {\n        path.push(home);\n        solver.add_complete_tour(path, weight + home_weight);\n        path.pop();\n    }\n}\n"
  },
  {
    "path": "rayon-demo/src/tsp/tour.rs",
    "content": "use std::cmp::Ordering;\nuse std::sync::Arc;\n\nuse super::graph::{Node, NodeSet};\nuse super::solver::TourId;\nuse super::weight::{Priority, Weight};\n\n#[derive(Clone, Debug)]\npub struct TourPrefix {\n    /// priority to visit, derived from a lower bound on how much weight we\n    /// have remaining to complete the tour\n    pub priority: Priority,\n\n    pub id: TourId,\n\n    /// the next node to traverse\n    pub node: Node,\n\n    /// total length of our tour\n    pub len: usize,\n\n    /// total weight of our tour so far\n    pub prefix_weight: Weight,\n\n    /// bit set with elements left to visit\n    pub visited: NodeSet,\n\n    /// we extend this; this is ordered last so that the `Ord` impl\n    /// won't look at it until the other fields\n    pub previous: Option<Arc<TourPrefix>>,\n}\n\nimpl TourPrefix {\n    /// Returns a tuple of stuff to use when comparing for ord/eq\n    fn to_cmp_elements(&self) -> (Priority, TourId) {\n        (self.priority, self.id)\n    }\n\n    pub fn visited(&self, node: Node) -> bool {\n        self.visited.contains(node)\n    }\n}\n\nimpl PartialEq for TourPrefix {\n    fn eq(&self, other: &Self) -> bool {\n        self.id == other.id\n    }\n}\n\nimpl Eq for TourPrefix {}\n\nimpl PartialOrd for TourPrefix {\n    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {\n        Some(self.cmp(other))\n    }\n}\n\nimpl Ord for TourPrefix {\n    fn cmp(&self, other: &Self) -> Ordering {\n        self.to_cmp_elements().cmp(&other.to_cmp_elements())\n    }\n}\n"
  },
  {
    "path": "rayon-demo/src/tsp/weight.rs",
    "content": "use std::ops::{Add, AddAssign, Sub, SubAssign};\n\n#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]\npub struct Weight {\n    weight: usize,\n}\n\n#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]\npub struct Priority {\n    priority: usize,\n}\n\nimpl Weight {\n    pub fn new(w: usize) -> Weight {\n        Weight { weight: w }\n    }\n\n    pub fn zero() -> Weight {\n        Weight::new(0)\n    }\n\n    pub fn max() -> Weight {\n        Weight { weight: usize::MAX }\n    }\n\n    pub fn to_usize(self) -> usize {\n        self.weight\n    }\n\n    pub fn is_max(self) -> bool {\n        self.weight == usize::MAX\n    }\n\n    /// Returns a priority for tours with this weight; lighter tours\n    /// have higher priority.\n    pub fn to_priority(self) -> Priority {\n        Priority {\n            priority: usize::MAX - self.weight,\n        }\n    }\n}\n\nimpl Add for Weight {\n    type Output = Weight;\n\n    fn add(self, rhs: Weight) -> Weight {\n        Weight::new(self.weight + rhs.weight)\n    }\n}\n\nimpl AddAssign for Weight {\n    fn add_assign(&mut self, rhs: Weight) {\n        *self = *self + rhs;\n    }\n}\n\nimpl Sub for Weight {\n    type Output = Weight;\n\n    fn sub(self, rhs: Weight) -> Weight {\n        Weight::new(self.weight - rhs.weight)\n    }\n}\n\nimpl SubAssign for Weight {\n    fn sub_assign(&mut self, rhs: Weight) {\n        *self = *self - rhs;\n    }\n}\n"
  },
  {
    "path": "rayon-demo/src/vec_collect.rs",
    "content": "//! Some benchmarks stress-testing various ways to build a standard `Vec`.\n\nmod util {\n    use rayon::prelude::*;\n    use std::collections::LinkedList;\n\n    /// Do whatever `collect` does by default.\n    pub fn collect<T, PI>(pi: PI) -> Vec<T>\n    where\n        T: Send,\n        PI: ParallelIterator<Item = T> + Send,\n    {\n        pi.collect()\n    }\n\n    /// Collect a linked list of vectors intermediary.\n    pub fn linked_list_collect_vec<T, PI>(pi: PI) -> Vec<T>\n    where\n        T: Send,\n        PI: ParallelIterator<Item = T> + Send,\n    {\n        let list: LinkedList<Vec<_>> = pi\n            .fold(Vec::new, |mut vec, elem| {\n                vec.push(elem);\n                vec\n            })\n            .collect();\n        list.into_iter().fold(Vec::new(), |mut vec, mut sub| {\n            vec.append(&mut sub);\n            vec\n        })\n    }\n\n    /// Collect a linked list of vectors intermediary, with a size hint.\n    pub fn linked_list_collect_vec_sized<T, PI>(pi: PI) -> Vec<T>\n    where\n        T: Send,\n        PI: ParallelIterator<Item = T> + Send,\n    {\n        let list: LinkedList<Vec<_>> = pi\n            .fold(Vec::new, |mut vec, elem| {\n                vec.push(elem);\n                vec\n            })\n            .collect();\n\n        let len = list.iter().map(Vec::len).sum();\n        list.into_iter()\n            .fold(Vec::with_capacity(len), |mut vec, mut sub| {\n                vec.append(&mut sub);\n                vec\n            })\n    }\n\n    /// Map-Reduce a linked list of vectors intermediary, with a size hint.\n    pub fn linked_list_map_reduce_vec_sized<T, PI>(pi: PI) -> Vec<T>\n    where\n        T: Send,\n        PI: ParallelIterator<Item = T> + Send,\n    {\n        let list: LinkedList<Vec<_>> = pi\n            .fold(Vec::new, |mut vec, elem| {\n                vec.push(elem);\n                vec\n            })\n            .map(|vec| {\n                let mut list = LinkedList::new();\n                list.push_back(vec);\n                list\n            })\n            .reduce(LinkedList::new, |mut list1, mut list2| {\n                list1.append(&mut list2);\n                list1\n            });\n\n        let len = list.iter().map(Vec::len).sum();\n        list.into_iter()\n            .fold(Vec::with_capacity(len), |mut vec, mut sub| {\n                vec.append(&mut sub);\n                vec\n            })\n    }\n\n    /// Map-Reduce a vector of vectors intermediary, with a size hint.\n    pub fn vec_vec_sized<T, PI>(pi: PI) -> Vec<T>\n    where\n        T: Send,\n        PI: ParallelIterator<Item = T> + Send,\n    {\n        let vecs: Vec<Vec<_>> = pi\n            .fold(Vec::new, |mut vec, elem| {\n                vec.push(elem);\n                vec\n            })\n            .map(|v| vec![v])\n            .reduce(Vec::new, |mut left, mut right| {\n                left.append(&mut right);\n                left\n            });\n\n        let len = vecs.iter().map(Vec::len).sum();\n        vecs.into_iter()\n            .fold(Vec::with_capacity(len), |mut vec, mut sub| {\n                vec.append(&mut sub);\n                vec\n            })\n    }\n\n    /// Fold into vectors and then reduce them together.\n    pub fn fold<T, PI>(pi: PI) -> Vec<T>\n    where\n        T: Send,\n        PI: ParallelIterator<Item = T> + Send,\n    {\n        pi.fold(Vec::new, |mut vec, x| {\n            vec.push(x);\n            vec\n        })\n        .reduce(Vec::new, |mut vec1, mut vec2| {\n            vec1.append(&mut vec2);\n            vec1\n        })\n    }\n}\n\nmacro_rules! make_bench {\n    ($generate:ident, $check:ident) => {\n        #[bench]\n        fn with_collect(b: &mut ::test::Bencher) {\n            use crate::vec_collect::util;\n            let mut vec = None;\n            b.iter(|| vec = Some(util::collect($generate())));\n            $check(&vec.unwrap());\n        }\n\n        #[bench]\n        fn with_linked_list_collect_vec(b: &mut ::test::Bencher) {\n            use crate::vec_collect::util;\n            let mut vec = None;\n            b.iter(|| vec = Some(util::linked_list_collect_vec($generate())));\n            $check(&vec.unwrap());\n        }\n\n        #[bench]\n        fn with_linked_list_collect_vec_sized(b: &mut ::test::Bencher) {\n            use crate::vec_collect::util;\n            let mut vec = None;\n            b.iter(|| vec = Some(util::linked_list_collect_vec_sized($generate())));\n            $check(&vec.unwrap());\n        }\n\n        #[bench]\n        fn with_linked_list_map_reduce_vec_sized(b: &mut ::test::Bencher) {\n            use crate::vec_collect::util;\n            let mut vec = None;\n            b.iter(|| vec = Some(util::linked_list_map_reduce_vec_sized($generate())));\n            $check(&vec.unwrap());\n        }\n\n        #[bench]\n        fn with_vec_vec_sized(b: &mut ::test::Bencher) {\n            use crate::vec_collect::util;\n            let mut vec = None;\n            b.iter(|| vec = Some(util::vec_vec_sized($generate())));\n            $check(&vec.unwrap());\n        }\n\n        #[bench]\n        fn with_fold(b: &mut ::test::Bencher) {\n            use crate::vec_collect::util;\n            let mut vec = None;\n            b.iter(|| vec = Some(util::fold($generate())));\n            $check(&vec.unwrap());\n        }\n    };\n}\n\n/// Tests a big vector of i forall i in 0 to N.\nmod vec_i {\n    use rayon::prelude::*;\n\n    const N: u32 = 4 * 1024 * 1024;\n\n    fn generate() -> impl IndexedParallelIterator<Item = u32> {\n        (0_u32..N).into_par_iter()\n    }\n\n    fn check(v: &[u32]) {\n        assert!(v.iter().cloned().eq(0..N));\n    }\n\n    #[bench]\n    fn with_collect_into_vec(b: &mut ::test::Bencher) {\n        let mut vec = None;\n        b.iter(|| {\n            let mut v = vec![];\n            generate().collect_into_vec(&mut v);\n            vec = Some(v);\n        });\n        check(&vec.unwrap());\n    }\n\n    #[bench]\n    fn with_collect_into_vec_reused(b: &mut ::test::Bencher) {\n        let mut vec = vec![];\n        b.iter(|| generate().collect_into_vec(&mut vec));\n        check(&vec);\n    }\n\n    make_bench!(generate, check);\n}\n\n/// Tests a big vector of i forall i in 0 to N, with a no-op\n/// filter just to make sure it's not an exact iterator.\nmod vec_i_filtered {\n    use rayon::prelude::*;\n\n    const N: u32 = 4 * 1024 * 1024;\n\n    fn generate() -> impl ParallelIterator<Item = u32> {\n        (0_u32..N).into_par_iter().filter(|_| true)\n    }\n\n    fn check(v: &[u32]) {\n        assert!(v.iter().cloned().eq(0..N));\n    }\n\n    make_bench!(generate, check);\n}\n"
  },
  {
    "path": "src/array.rs",
    "content": "//! Parallel iterator types for [arrays] (`[T; N]`)\n//!\n//! You will rarely need to interact with this module directly unless you need\n//! to name one of the iterator types.\n//!\n//! [arrays]: primitive@array\n\nuse crate::iter::plumbing::*;\nuse crate::iter::*;\nuse crate::slice::{Iter, IterMut};\nuse crate::vec::DrainProducer;\nuse std::mem::ManuallyDrop;\n\nimpl<'data, T: Sync + 'data, const N: usize> IntoParallelIterator for &'data [T; N] {\n    type Item = &'data T;\n    type Iter = Iter<'data, T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        <&[T]>::into_par_iter(self)\n    }\n}\n\nimpl<'data, T: Send + 'data, const N: usize> IntoParallelIterator for &'data mut [T; N] {\n    type Item = &'data mut T;\n    type Iter = IterMut<'data, T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        <&mut [T]>::into_par_iter(self)\n    }\n}\n\nimpl<T: Send, const N: usize> IntoParallelIterator for [T; N] {\n    type Item = T;\n    type Iter = IntoIter<T, N>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        IntoIter { array: self }\n    }\n}\n\n/// Parallel iterator that moves out of an array.\n#[derive(Debug, Clone)]\npub struct IntoIter<T, const N: usize> {\n    array: [T; N],\n}\n\nimpl<T: Send, const N: usize> ParallelIterator for IntoIter<T, N> {\n    type Item = T;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(N)\n    }\n}\n\nimpl<T: Send, const N: usize> IndexedParallelIterator for IntoIter<T, N> {\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        N\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        unsafe {\n            // Drain every item, and then the local array can just fall out of scope.\n            let mut array = ManuallyDrop::new(self.array);\n            let producer = DrainProducer::new(array.as_mut_slice());\n            callback.callback(producer)\n        }\n    }\n}\n"
  },
  {
    "path": "src/collections/binary_heap.rs",
    "content": "//! This module contains the parallel iterator types for heaps\n//! (`BinaryHeap<T>`). You will rarely need to interact with it directly\n//! unless you have need to name one of the iterator types.\n\nuse std::collections::BinaryHeap;\n\nuse crate::iter::plumbing::*;\nuse crate::iter::*;\n\nuse crate::slice;\nuse crate::vec;\n\n/// Parallel iterator over a binary heap\n#[derive(Debug, Clone)]\npub struct IntoIter<T> {\n    inner: vec::IntoIter<T>,\n}\n\nimpl<T: Send> IntoParallelIterator for BinaryHeap<T> {\n    type Item = T;\n    type Iter = IntoIter<T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        IntoIter {\n            inner: Vec::from(self).into_par_iter(),\n        }\n    }\n}\n\ndelegate_indexed_iterator! {\n    IntoIter<T> => T,\n    impl<T: Send>\n}\n\n/// Parallel iterator over an immutable reference to a binary heap\n#[derive(Debug)]\npub struct Iter<'a, T> {\n    inner: slice::Iter<'a, T>,\n}\n\nimpl<T> Clone for Iter<'_, T> {\n    fn clone(&self) -> Self {\n        Iter {\n            inner: self.inner.clone(),\n        }\n    }\n}\n\nimpl<'a, T: Sync> IntoParallelIterator for &'a BinaryHeap<T> {\n    type Item = &'a T;\n    type Iter = Iter<'a, T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        Iter {\n            inner: self.as_slice().into_par_iter(),\n        }\n    }\n}\n\ndelegate_indexed_iterator! {\n    Iter<'a, T> => &'a T,\n    impl<'a, T: Sync + 'a>\n}\n\n// `BinaryHeap` doesn't have a mutable `Iterator`\n\n/// Draining parallel iterator that moves out of a binary heap,\n/// but keeps the total capacity.\n#[derive(Debug)]\npub struct Drain<'a, T> {\n    heap: &'a mut BinaryHeap<T>,\n}\n\n// NB: The only reason we require `T: Ord` is for `DrainGuard` to reconstruct\n// the heap `From<Vec<T>>` afterward, even though that will actually be empty.\nimpl<'a, T: Ord + Send> ParallelDrainFull for &'a mut BinaryHeap<T> {\n    type Iter = Drain<'a, T>;\n    type Item = T;\n\n    fn par_drain(self) -> Self::Iter {\n        Drain { heap: self }\n    }\n}\n\nimpl<T: Ord + Send> ParallelIterator for Drain<'_, T> {\n    type Item = T;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<T: Ord + Send> IndexedParallelIterator for Drain<'_, T> {\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.heap.len()\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        super::DrainGuard::new(self.heap)\n            .par_drain(..)\n            .with_producer(callback)\n    }\n}\n\nimpl<T> Drop for Drain<'_, T> {\n    fn drop(&mut self) {\n        if !self.heap.is_empty() {\n            // We must not have produced, so just call a normal drain to remove the items.\n            self.heap.drain();\n        }\n    }\n}\n"
  },
  {
    "path": "src/collections/btree_map.rs",
    "content": "//! This module contains the parallel iterator types for B-Tree maps\n//! (`BTreeMap<K, V>`). You will rarely need to interact with it directly\n//! unless you have need to name one of the iterator types.\n\nuse std::collections::BTreeMap;\n\nuse crate::iter::plumbing::*;\nuse crate::iter::*;\n\nuse crate::vec;\n\n/// Parallel iterator over a B-Tree map\n#[derive(Debug)] // std doesn't Clone\npub struct IntoIter<K, V> {\n    inner: vec::IntoIter<(K, V)>,\n}\n\ninto_par_vec! {\n    BTreeMap<K, V> => IntoIter<K, V>,\n    impl<K: Send, V: Send>\n}\n\ndelegate_iterator! {\n    IntoIter<K, V> => (K, V),\n    impl<K: Send, V: Send>\n}\n\n/// Parallel iterator over an immutable reference to a B-Tree map\n#[derive(Debug)]\npub struct Iter<'a, K, V> {\n    inner: vec::IntoIter<(&'a K, &'a V)>,\n}\n\nimpl<K, V> Clone for Iter<'_, K, V> {\n    fn clone(&self) -> Self {\n        Iter {\n            inner: self.inner.clone(),\n        }\n    }\n}\n\ninto_par_vec! {\n    &'a BTreeMap<K, V> => Iter<'a, K, V>,\n    impl<'a, K: Sync, V: Sync>\n}\n\ndelegate_iterator! {\n    Iter<'a, K, V> => (&'a K, &'a V),\n    impl<'a, K: Sync + 'a, V: Sync + 'a>\n}\n\n/// Parallel iterator over a mutable reference to a B-Tree map\n#[derive(Debug)]\npub struct IterMut<'a, K, V> {\n    inner: vec::IntoIter<(&'a K, &'a mut V)>,\n}\n\ninto_par_vec! {\n    &'a mut BTreeMap<K, V> => IterMut<'a, K, V>,\n    impl<'a, K: Sync, V: Send>\n}\n\ndelegate_iterator! {\n    IterMut<'a, K, V> => (&'a K, &'a mut V),\n    impl<'a, K: Sync + 'a, V: Send + 'a>\n}\n"
  },
  {
    "path": "src/collections/btree_set.rs",
    "content": "//! This module contains the parallel iterator types for B-Tree sets\n//! (`BTreeSet<T>`). You will rarely need to interact with it directly\n//! unless you have need to name one of the iterator types.\n\nuse std::collections::BTreeSet;\n\nuse crate::iter::plumbing::*;\nuse crate::iter::*;\n\nuse crate::vec;\n\n/// Parallel iterator over a B-Tree set\n#[derive(Debug)] // std doesn't Clone\npub struct IntoIter<T> {\n    inner: vec::IntoIter<T>,\n}\n\ninto_par_vec! {\n    BTreeSet<T> => IntoIter<T>,\n    impl<T: Send>\n}\n\ndelegate_iterator! {\n    IntoIter<T> => T,\n    impl<T: Send>\n}\n\n/// Parallel iterator over an immutable reference to a B-Tree set\n#[derive(Debug)]\npub struct Iter<'a, T> {\n    inner: vec::IntoIter<&'a T>,\n}\n\nimpl<T> Clone for Iter<'_, T> {\n    fn clone(&self) -> Self {\n        Iter {\n            inner: self.inner.clone(),\n        }\n    }\n}\n\ninto_par_vec! {\n    &'a BTreeSet<T> => Iter<'a, T>,\n    impl<'a, T: Sync>\n}\n\ndelegate_iterator! {\n    Iter<'a, T> => &'a T,\n    impl<'a, T: Sync + 'a>\n}\n\n// `BTreeSet` doesn't have a mutable `Iterator`\n"
  },
  {
    "path": "src/collections/hash_map.rs",
    "content": "//! This module contains the parallel iterator types for hash maps\n//! (`HashMap<K, V>`). You will rarely need to interact with it directly\n//! unless you have need to name one of the iterator types.\n\nuse std::collections::HashMap;\nuse std::marker::PhantomData;\n\nuse crate::iter::plumbing::*;\nuse crate::iter::*;\n\nuse crate::vec;\n\n/// Parallel iterator over a hash map\n#[derive(Debug)] // std doesn't Clone\npub struct IntoIter<K, V> {\n    inner: vec::IntoIter<(K, V)>,\n}\n\ninto_par_vec! {\n    HashMap<K, V, S> => IntoIter<K, V>,\n    impl<K: Send, V: Send, S>\n}\n\ndelegate_iterator! {\n    IntoIter<K, V> => (K, V),\n    impl<K: Send, V: Send>\n}\n\n/// Parallel iterator over an immutable reference to a hash map\n#[derive(Debug)]\npub struct Iter<'a, K, V> {\n    inner: vec::IntoIter<(&'a K, &'a V)>,\n}\n\nimpl<K, V> Clone for Iter<'_, K, V> {\n    fn clone(&self) -> Self {\n        Iter {\n            inner: self.inner.clone(),\n        }\n    }\n}\n\ninto_par_vec! {\n    &'a HashMap<K, V, S> => Iter<'a, K, V>,\n    impl<'a, K: Sync, V: Sync, S>\n}\n\ndelegate_iterator! {\n    Iter<'a, K, V> => (&'a K, &'a V),\n    impl<'a, K: Sync, V: Sync>\n}\n\n/// Parallel iterator over a mutable reference to a hash map\n#[derive(Debug)]\npub struct IterMut<'a, K, V> {\n    inner: vec::IntoIter<(&'a K, &'a mut V)>,\n}\n\ninto_par_vec! {\n    &'a mut HashMap<K, V, S> => IterMut<'a, K, V>,\n    impl<'a, K: Sync, V: Send, S>\n}\n\ndelegate_iterator! {\n    IterMut<'a, K, V> => (&'a K, &'a mut V),\n    impl<'a, K: Sync, V: Send>\n}\n\n/// Draining parallel iterator that moves out of a hash map,\n/// but keeps the total capacity.\n#[derive(Debug)]\npub struct Drain<'a, K, V> {\n    inner: vec::IntoIter<(K, V)>,\n    marker: PhantomData<&'a mut HashMap<K, V>>,\n}\n\nimpl<'a, K: Send, V: Send, S> ParallelDrainFull for &'a mut HashMap<K, V, S> {\n    type Iter = Drain<'a, K, V>;\n    type Item = (K, V);\n\n    fn par_drain(self) -> Self::Iter {\n        let vec: Vec<_> = self.drain().collect();\n        Drain {\n            inner: vec.into_par_iter(),\n            marker: PhantomData,\n        }\n    }\n}\n\ndelegate_iterator! {\n    Drain<'_, K, V> => (K, V),\n    impl<K: Send, V: Send>\n}\n"
  },
  {
    "path": "src/collections/hash_set.rs",
    "content": "//! This module contains the parallel iterator types for hash sets\n//! (`HashSet<T>`). You will rarely need to interact with it directly\n//! unless you have need to name one of the iterator types.\n\nuse std::collections::HashSet;\nuse std::marker::PhantomData;\n\nuse crate::iter::plumbing::*;\nuse crate::iter::*;\n\nuse crate::vec;\n\n/// Parallel iterator over a hash set\n#[derive(Debug)] // std doesn't Clone\npub struct IntoIter<T> {\n    inner: vec::IntoIter<T>,\n}\n\ninto_par_vec! {\n    HashSet<T, S> => IntoIter<T>,\n    impl<T: Send, S>\n}\n\ndelegate_iterator! {\n    IntoIter<T> => T,\n    impl<T: Send>\n}\n\n/// Parallel iterator over an immutable reference to a hash set\n#[derive(Debug)]\npub struct Iter<'a, T> {\n    inner: vec::IntoIter<&'a T>,\n}\n\nimpl<T> Clone for Iter<'_, T> {\n    fn clone(&self) -> Self {\n        Iter {\n            inner: self.inner.clone(),\n        }\n    }\n}\n\ninto_par_vec! {\n    &'a HashSet<T, S> => Iter<'a, T>,\n    impl<'a, T: Sync, S>\n}\n\ndelegate_iterator! {\n    Iter<'a, T> => &'a T,\n    impl<'a, T: Sync>\n}\n\n// `HashSet` doesn't have a mutable `Iterator`\n\n/// Draining parallel iterator that moves out of a hash set,\n/// but keeps the total capacity.\n#[derive(Debug)]\npub struct Drain<'a, T> {\n    inner: vec::IntoIter<T>,\n    marker: PhantomData<&'a mut HashSet<T>>,\n}\n\nimpl<'a, T: Send, S> ParallelDrainFull for &'a mut HashSet<T, S> {\n    type Iter = Drain<'a, T>;\n    type Item = T;\n\n    fn par_drain(self) -> Self::Iter {\n        let vec: Vec<_> = self.drain().collect();\n        Drain {\n            inner: vec.into_par_iter(),\n            marker: PhantomData,\n        }\n    }\n}\n\ndelegate_iterator! {\n    Drain<'_, T> => T,\n    impl<T: Send>\n}\n"
  },
  {
    "path": "src/collections/linked_list.rs",
    "content": "//! This module contains the parallel iterator types for linked lists\n//! (`LinkedList<T>`). You will rarely need to interact with it directly\n//! unless you have need to name one of the iterator types.\n\nuse std::collections::LinkedList;\n\nuse crate::iter::plumbing::*;\nuse crate::iter::*;\n\nuse crate::vec;\n\n/// Parallel iterator over a linked list\n#[derive(Debug, Clone)]\npub struct IntoIter<T> {\n    inner: vec::IntoIter<T>,\n}\n\ninto_par_vec! {\n    LinkedList<T> => IntoIter<T>,\n    impl<T: Send>\n}\n\ndelegate_iterator! {\n    IntoIter<T> => T,\n    impl<T: Send>\n}\n\n/// Parallel iterator over an immutable reference to a linked list\n#[derive(Debug)]\npub struct Iter<'a, T> {\n    inner: vec::IntoIter<&'a T>,\n}\n\nimpl<T> Clone for Iter<'_, T> {\n    fn clone(&self) -> Self {\n        Iter {\n            inner: self.inner.clone(),\n        }\n    }\n}\n\ninto_par_vec! {\n    &'a LinkedList<T> => Iter<'a, T>,\n    impl<'a, T: Sync>\n}\n\ndelegate_iterator! {\n    Iter<'a, T> => &'a T,\n    impl<'a, T: Sync>\n}\n\n/// Parallel iterator over a mutable reference to a linked list\n#[derive(Debug)]\npub struct IterMut<'a, T> {\n    inner: vec::IntoIter<&'a mut T>,\n}\n\ninto_par_vec! {\n    &'a mut LinkedList<T> => IterMut<'a, T>,\n    impl<'a, T: Send>\n}\n\ndelegate_iterator! {\n    IterMut<'a, T> => &'a mut T,\n    impl<'a, T: Send>\n}\n"
  },
  {
    "path": "src/collections/mod.rs",
    "content": "//! Parallel iterator types for [standard collections]\n//!\n//! You will rarely need to interact with this module directly unless you need\n//! to name one of the iterator types.\n//!\n//! [standard collections]: std::collections\n\n/// Convert an iterable collection into a parallel iterator by first\n/// collecting into a temporary `Vec`, then iterating that.\nmacro_rules! into_par_vec {\n    ($t:ty => $iter:ident<$($i:tt),*>, impl $($args:tt)*) => {\n        impl $($args)* IntoParallelIterator for $t {\n            type Item = <$t as IntoIterator>::Item;\n            type Iter = $iter<$($i),*>;\n\n            fn into_par_iter(self) -> Self::Iter {\n                use std::iter::FromIterator;\n                $iter { inner: Vec::from_iter(self).into_par_iter() }\n            }\n        }\n    };\n}\n\npub mod binary_heap;\npub mod btree_map;\npub mod btree_set;\npub mod hash_map;\npub mod hash_set;\npub mod linked_list;\npub mod vec_deque;\n\nuse self::drain_guard::DrainGuard;\n\nmod drain_guard {\n    use crate::iter::ParallelDrainRange;\n    use std::mem;\n    use std::ops::RangeBounds;\n\n    /// A proxy for draining a collection by converting to a `Vec` and back.\n    ///\n    /// This is used for draining `BinaryHeap` and `VecDeque`, which both have\n    /// zero-allocation conversions to/from `Vec`, though not zero-cost:\n    /// - `BinaryHeap` will heapify from `Vec`, but at least that will be empty.\n    /// - `VecDeque` has to shift items to offset 0 when converting to `Vec`.\n    #[allow(missing_debug_implementations)]\n    pub(super) struct DrainGuard<'a, T, C: From<Vec<T>>> {\n        collection: &'a mut C,\n        vec: Vec<T>,\n    }\n\n    impl<'a, T, C> DrainGuard<'a, T, C>\n    where\n        C: Default + From<Vec<T>>,\n        Vec<T>: From<C>,\n    {\n        pub(super) fn new(collection: &'a mut C) -> Self {\n            Self {\n                // Temporarily steal the inner `Vec` so we can drain in place.\n                vec: Vec::from(mem::take(collection)),\n                collection,\n            }\n        }\n    }\n\n    impl<'a, T, C: From<Vec<T>>> Drop for DrainGuard<'a, T, C> {\n        fn drop(&mut self) {\n            // Restore the collection from the `Vec` with its original capacity.\n            *self.collection = C::from(mem::take(&mut self.vec));\n        }\n    }\n\n    impl<'a, T, C> ParallelDrainRange<usize> for &'a mut DrainGuard<'_, T, C>\n    where\n        T: Send,\n        C: From<Vec<T>>,\n    {\n        type Iter = crate::vec::Drain<'a, T>;\n        type Item = T;\n\n        fn par_drain<R: RangeBounds<usize>>(self, range: R) -> Self::Iter {\n            self.vec.par_drain(range)\n        }\n    }\n}\n"
  },
  {
    "path": "src/collections/vec_deque.rs",
    "content": "//! This module contains the parallel iterator types for double-ended queues\n//! (`VecDeque<T>`). You will rarely need to interact with it directly\n//! unless you have need to name one of the iterator types.\n\nuse std::collections::VecDeque;\nuse std::ops::{Range, RangeBounds};\n\nuse crate::iter::plumbing::*;\nuse crate::iter::*;\nuse crate::math::simplify_range;\n\nuse crate::slice;\nuse crate::vec;\n\n/// Parallel iterator over a double-ended queue\n#[derive(Debug, Clone)]\npub struct IntoIter<T: Send> {\n    inner: vec::IntoIter<T>,\n}\n\nimpl<T: Send> IntoParallelIterator for VecDeque<T> {\n    type Item = T;\n    type Iter = IntoIter<T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        // NOTE: requires data movement if the deque doesn't start at offset 0.\n        let inner = Vec::from(self).into_par_iter();\n        IntoIter { inner }\n    }\n}\n\ndelegate_indexed_iterator! {\n    IntoIter<T> => T,\n    impl<T: Send>\n}\n\n/// Parallel iterator over an immutable reference to a double-ended queue\n#[derive(Debug)]\npub struct Iter<'a, T> {\n    inner: Chain<slice::Iter<'a, T>, slice::Iter<'a, T>>,\n}\n\nimpl<T> Clone for Iter<'_, T> {\n    fn clone(&self) -> Self {\n        Iter {\n            inner: self.inner.clone(),\n        }\n    }\n}\n\nimpl<'a, T: Sync> IntoParallelIterator for &'a VecDeque<T> {\n    type Item = &'a T;\n    type Iter = Iter<'a, T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        let (a, b) = self.as_slices();\n        Iter {\n            inner: a.into_par_iter().chain(b),\n        }\n    }\n}\n\ndelegate_indexed_iterator! {\n    Iter<'a, T> => &'a T,\n    impl<'a, T: Sync>\n}\n\n/// Parallel iterator over a mutable reference to a double-ended queue\n#[derive(Debug)]\npub struct IterMut<'a, T> {\n    inner: Chain<slice::IterMut<'a, T>, slice::IterMut<'a, T>>,\n}\n\nimpl<'a, T: Send> IntoParallelIterator for &'a mut VecDeque<T> {\n    type Item = &'a mut T;\n    type Iter = IterMut<'a, T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        let (a, b) = self.as_mut_slices();\n        IterMut {\n            inner: a.into_par_iter().chain(b),\n        }\n    }\n}\n\ndelegate_indexed_iterator! {\n    IterMut<'a, T> => &'a mut T,\n    impl<'a, T: Send>\n}\n\n/// Draining parallel iterator that moves a range out of a double-ended queue,\n/// but keeps the total capacity.\n#[derive(Debug)]\npub struct Drain<'a, T> {\n    deque: &'a mut VecDeque<T>,\n    range: Range<usize>,\n    orig_len: usize,\n}\n\nimpl<'a, T: Send> ParallelDrainRange<usize> for &'a mut VecDeque<T> {\n    type Iter = Drain<'a, T>;\n    type Item = T;\n\n    fn par_drain<R: RangeBounds<usize>>(self, range: R) -> Self::Iter {\n        Drain {\n            orig_len: self.len(),\n            range: simplify_range(range, self.len()),\n            deque: self,\n        }\n    }\n}\n\nimpl<T: Send> ParallelIterator for Drain<'_, T> {\n    type Item = T;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<T: Send> IndexedParallelIterator for Drain<'_, T> {\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.range.len()\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        // NOTE: requires data movement if the deque doesn't start at offset 0.\n        super::DrainGuard::new(self.deque)\n            .par_drain(self.range.clone())\n            .with_producer(callback)\n    }\n}\n\nimpl<T> Drop for Drain<'_, T> {\n    fn drop(&mut self) {\n        if self.deque.len() != self.orig_len - self.range.len() {\n            // We must not have produced, so just call a normal drain to remove the items.\n            assert_eq!(self.deque.len(), self.orig_len);\n            self.deque.drain(self.range.clone());\n        }\n    }\n}\n"
  },
  {
    "path": "src/compile_fail/cannot_collect_filtermap_data.rs",
    "content": "/*! ```compile_fail,E0599\n\nuse rayon::prelude::*;\n\n// zip requires data of exact size, but filter yields only bounded\n// size, so check that we cannot apply it.\n\nlet a: Vec<usize> = (0..1024).collect();\nlet mut v = vec![];\na.par_iter()\n    .filter_map(|&x| Some(x as f32))\n    .collect_into_vec(&mut v); //~ ERROR no method\n\n``` */\n"
  },
  {
    "path": "src/compile_fail/cannot_zip_filtered_data.rs",
    "content": "/*! ```compile_fail,E0277\n\nuse rayon::prelude::*;\n\n// zip requires data of exact size, but filter yields only bounded\n// size, so check that we cannot apply it.\n\nlet mut a: Vec<usize> = (0..1024).rev().collect();\nlet b: Vec<usize> = (0..1024).collect();\n\na.par_iter()\n    .zip(b.par_iter().filter(|&&x| x > 3)); //~ ERROR\n\n``` */\n"
  },
  {
    "path": "src/compile_fail/cell_par_iter.rs",
    "content": "/*! ```compile_fail,E0277\n\n// Check that we can't use the par-iter API to access contents of a `Cell`.\n\nuse rayon::prelude::*;\nuse std::cell::Cell;\n\nlet c = Cell::new(42_i32);\n(0_i32..1024).into_par_iter()\n    .map(|_| c.get()) //~ ERROR E0277\n    .min();\n\n``` */\n"
  },
  {
    "path": "src/compile_fail/mod.rs",
    "content": "// These modules contain `compile_fail` doc tests.\nmod cannot_collect_filtermap_data;\nmod cannot_zip_filtered_data;\nmod cell_par_iter;\nmod must_use;\nmod no_send_par_iter;\nmod rc_par_iter;\n"
  },
  {
    "path": "src/compile_fail/must_use.rs",
    "content": "// Check that we are flagged for ignoring `must_use` parallel adaptors.\n// (unfortunately there's no error code for `unused_must_use`)\n\nmacro_rules! must_use {\n    ($( $name:ident #[$expr:meta] )*) => {$(\n        /// First sanity check that the expression is OK.\n        ///\n        /// ```\n        /// #![deny(unused_must_use)]\n        ///\n        /// use rayon::prelude::*;\n        ///\n        /// let v: Vec<_> = (0..100).map(Some).collect();\n        /// let _ =\n        #[$expr]\n        /// ```\n        ///\n        /// Now trigger the `must_use`.\n        ///\n        /// ```compile_fail\n        /// #![deny(unused_must_use)]\n        ///\n        /// use rayon::prelude::*;\n        ///\n        /// let v: Vec<_> = (0..100).map(Some).collect();\n        #[$expr]\n        /// ```\n        mod $name {}\n    )*}\n}\n\nmust_use! {\n    by_exponential_blocks  /** v.par_iter().by_exponential_blocks(); */\n    by_uniform_blocks   /** v.par_iter().by_uniform_blocks(2); */\n    step_by             /** v.par_iter().step_by(2); */\n    chain               /** v.par_iter().chain(&v); */\n    chunks              /** v.par_iter().chunks(2); */\n    fold_chunks         /** v.par_iter().fold_chunks(2, || 0, |x, _| x); */\n    fold_chunks_with    /** v.par_iter().fold_chunks_with(2, 0, |x, _| x); */\n    cloned              /** v.par_iter().cloned(); */\n    copied              /** v.par_iter().copied(); */\n    enumerate           /** v.par_iter().enumerate(); */\n    filter              /** v.par_iter().filter(|_| true); */\n    filter_map          /** v.par_iter().filter_map(|x| *x); */\n    flat_map            /** v.par_iter().flat_map(|x| *x); */\n    flat_map_iter       /** v.par_iter().flat_map_iter(|x| *x); */\n    flatten             /** v.par_iter().flatten(); */\n    flatten_iter        /** v.par_iter().flatten_iter(); */\n    fold                /** v.par_iter().fold(|| 0, |x, _| x); */\n    fold_with           /** v.par_iter().fold_with(0, |x, _| x); */\n    try_fold            /** v.par_iter().try_fold(|| 0, |x, _| Some(x)); */\n    try_fold_with       /** v.par_iter().try_fold_with(0, |x, _| Some(x)); */\n    inspect             /** v.par_iter().inspect(|_| {}); */\n    interleave          /** v.par_iter().interleave(&v); */\n    interleave_shortest /** v.par_iter().interleave_shortest(&v); */\n    intersperse         /** v.par_iter().intersperse(&None); */\n    map                 /** v.par_iter().map(|x| x); */\n    map_with            /** v.par_iter().map_with(0, |_, x| x); */\n    map_init            /** v.par_iter().map_init(|| 0, |_, x| x); */\n    panic_fuse          /** v.par_iter().panic_fuse(); */\n    positions           /** v.par_iter().positions(|_| true); */\n    rev                 /** v.par_iter().rev(); */\n    skip                /** v.par_iter().skip(1); */\n    take                /** v.par_iter().take(1); */\n    update              /** v.par_iter().update(|_| {}); */\n    while_some          /** v.par_iter().cloned().while_some(); */\n    with_max_len        /** v.par_iter().with_max_len(1); */\n    with_min_len        /** v.par_iter().with_min_len(1); */\n    zip                 /** v.par_iter().zip(&v); */\n    zip_eq              /** v.par_iter().zip_eq(&v); */\n}\n"
  },
  {
    "path": "src/compile_fail/no_send_par_iter.rs",
    "content": "// Check that `!Send` types fail early.\n\n/** ```compile_fail,E0277\n\nuse rayon::prelude::*;\nuse std::ptr::null;\n\n#[derive(Copy, Clone)]\nstruct NoSend(*const ());\n\nunsafe impl Sync for NoSend {}\n\nlet x = Some(NoSend(null()));\n\nx.par_iter()\n    .map(|&x| x) //~ ERROR\n    .count(); //~ ERROR\n\n``` */\nmod map {}\n\n/** ```compile_fail,E0277\n\nuse rayon::prelude::*;\nuse std::ptr::null;\n\n#[derive(Copy, Clone)]\nstruct NoSend(*const ());\n\nunsafe impl Sync for NoSend {}\n\nlet x = Some(NoSend(null()));\n\nx.par_iter()\n    .filter_map(|&x| Some(x)) //~ ERROR\n    .count(); //~ ERROR\n\n``` */\nmod filter_map {}\n\n/** ```compile_fail,E0277\n\nuse rayon::prelude::*;\nuse std::ptr::null;\n\n#[derive(Copy, Clone)]\nstruct NoSend(*const ());\n\nunsafe impl Sync for NoSend {}\n\nlet x = Some(NoSend(null()));\n\nx.par_iter()\n    .cloned() //~ ERROR\n    .count(); //~ ERROR\n\n``` */\nmod cloned {}\n"
  },
  {
    "path": "src/compile_fail/rc_par_iter.rs",
    "content": "/*! ```compile_fail,E0599\n\n// Check that we can't use the par-iter API to access contents of an\n// `Rc`.\n\nuse rayon::prelude::*;\nuse std::rc::Rc;\n\nlet x = vec![Rc::new(22), Rc::new(23)];\nlet mut y = vec![];\nx.into_par_iter() //~ ERROR no method named `into_par_iter`\n    .map(|rc| *rc)\n    .collect_into_vec(&mut y);\n\n``` */\n"
  },
  {
    "path": "src/delegate.rs",
    "content": "//! Macros for delegating newtype iterators to inner types.\n\n// Note: these place `impl` bounds at the end, as token gobbling is the only way\n// I know how to consume an arbitrary list of constraints, with `$($args:tt)*`.\n\n/// Creates a parallel iterator implementation which simply wraps an inner type\n/// and delegates all methods inward.  The actual struct must already be\n/// declared with an `inner` field.\n///\n/// The implementation of `IntoParallelIterator` should be added separately.\nmacro_rules! delegate_iterator {\n    ($iter:ty => $item:ty ,\n     impl $( $args:tt )*\n     ) => {\n        impl $( $args )* ParallelIterator for $iter {\n            type Item = $item;\n\n            fn drive_unindexed<C>(self, consumer: C) -> C::Result\n                where C: UnindexedConsumer<Self::Item>\n            {\n                self.inner.drive_unindexed(consumer)\n            }\n\n            fn opt_len(&self) -> Option<usize> {\n                self.inner.opt_len()\n            }\n        }\n    }\n}\n\n/// Creates an indexed parallel iterator implementation which simply wraps an\n/// inner type and delegates all methods inward.  The actual struct must already\n/// be declared with an `inner` field.\nmacro_rules! delegate_indexed_iterator {\n    ($iter:ty => $item:ty ,\n     impl $( $args:tt )*\n     ) => {\n        delegate_iterator!{\n            $iter => $item ,\n            impl $( $args )*\n        }\n\n        impl $( $args )* IndexedParallelIterator for $iter {\n            fn drive<C>(self, consumer: C) -> C::Result\n                where C: Consumer<Self::Item>\n            {\n                self.inner.drive(consumer)\n            }\n\n            fn len(&self) -> usize {\n                self.inner.len()\n            }\n\n            fn with_producer<CB>(self, callback: CB) -> CB::Output\n                where CB: ProducerCallback<Self::Item>\n            {\n                self.inner.with_producer(callback)\n            }\n        }\n    }\n}\n\n#[test]\nfn unindexed_example() {\n    use crate::collections::btree_map::IntoIter;\n    use crate::iter::plumbing::*;\n    use crate::prelude::*;\n\n    use std::collections::BTreeMap;\n\n    struct MyIntoIter<T: Ord + Send, U: Send> {\n        inner: IntoIter<T, U>,\n    }\n\n    delegate_iterator! {\n        MyIntoIter<T, U> => (T, U),\n        impl<T: Ord + Send, U: Send>\n    }\n\n    let map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);\n    let iter = MyIntoIter {\n        inner: map.into_par_iter(),\n    };\n    let vec: Vec<_> = iter.map(|(k, _)| k).collect();\n    assert_eq!(vec, &[1, 2, 3]);\n}\n\n#[test]\nfn indexed_example() {\n    use crate::iter::plumbing::*;\n    use crate::prelude::*;\n    use crate::vec::IntoIter;\n\n    struct MyIntoIter<T: Send> {\n        inner: IntoIter<T>,\n    }\n\n    delegate_indexed_iterator! {\n        MyIntoIter<T> => T,\n        impl<T: Send>\n    }\n\n    let iter = MyIntoIter {\n        inner: vec![1, 2, 3].into_par_iter(),\n    };\n    let mut vec = vec![];\n    iter.collect_into_vec(&mut vec);\n    assert_eq!(vec, &[1, 2, 3]);\n}\n"
  },
  {
    "path": "src/iter/blocks.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\nstruct BlocksCallback<S, C> {\n    sizes: S,\n    consumer: C,\n    len: usize,\n}\n\nimpl<T, S, C> ProducerCallback<T> for BlocksCallback<S, C>\nwhere\n    C: UnindexedConsumer<T>,\n    S: Iterator<Item = usize>,\n{\n    type Output = C::Result;\n\n    fn callback<P: Producer<Item = T>>(mut self, mut producer: P) -> Self::Output {\n        let mut remaining_len = self.len;\n        let mut consumer = self.consumer;\n\n        // we need a local variable for the accumulated results\n        // we call the reducer's identity by splitting at 0\n        let (left_consumer, right_consumer, _) = consumer.split_at(0);\n        let mut leftmost_res = left_consumer.into_folder().complete();\n        consumer = right_consumer;\n\n        // now we loop on each block size\n        while remaining_len > 0 && !consumer.full() {\n            // we compute the next block's size\n            let size = self.sizes.next().unwrap_or(usize::MAX);\n            let capped_size = remaining_len.min(size);\n            remaining_len -= capped_size;\n\n            // split the producer\n            let (left_producer, right_producer) = producer.split_at(capped_size);\n            producer = right_producer;\n\n            // split the consumer\n            let (left_consumer, right_consumer, _) = consumer.split_at(capped_size);\n            consumer = right_consumer;\n\n            leftmost_res = consumer.to_reducer().reduce(\n                leftmost_res,\n                bridge_producer_consumer(capped_size, left_producer, left_consumer),\n            );\n        }\n        leftmost_res\n    }\n}\n\n/// `ExponentialBlocks` is a parallel iterator that consumes itself as a sequence\n/// of parallel blocks of increasing sizes (exponentially).\n///\n/// This struct is created by the [`by_exponential_blocks()`] method on [`IndexedParallelIterator`]\n///\n/// [`by_exponential_blocks()`]: IndexedParallelIterator::by_exponential_blocks()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\npub struct ExponentialBlocks<I> {\n    base: I,\n}\n\nimpl<I> ExponentialBlocks<I> {\n    pub(super) fn new(base: I) -> Self {\n        Self { base }\n    }\n}\n\nimpl<I> ParallelIterator for ExponentialBlocks<I>\nwhere\n    I: IndexedParallelIterator,\n{\n    type Item = I::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let first = crate::current_num_threads();\n        let callback = BlocksCallback {\n            consumer,\n            sizes: std::iter::successors(Some(first), exponential_size),\n            len: self.base.len(),\n        };\n        self.base.with_producer(callback)\n    }\n}\n\nfn exponential_size(size: &usize) -> Option<usize> {\n    Some(size.saturating_mul(2))\n}\n\n/// `UniformBlocks` is a parallel iterator that consumes itself as a sequence\n/// of parallel blocks of constant sizes.\n///\n/// This struct is created by the [`by_uniform_blocks()`] method on [`IndexedParallelIterator`]\n///\n/// [`by_uniform_blocks()`]: IndexedParallelIterator::by_uniform_blocks()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\npub struct UniformBlocks<I> {\n    base: I,\n    block_size: usize,\n}\n\nimpl<I> UniformBlocks<I> {\n    pub(super) fn new(base: I, block_size: usize) -> Self {\n        Self { base, block_size }\n    }\n}\n\nimpl<I> ParallelIterator for UniformBlocks<I>\nwhere\n    I: IndexedParallelIterator,\n{\n    type Item = I::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let callback = BlocksCallback {\n            consumer,\n            sizes: std::iter::repeat(self.block_size),\n            len: self.base.len(),\n        };\n        self.base.with_producer(callback)\n    }\n}\n"
  },
  {
    "path": "src/iter/chain.rs",
    "content": "use super::plumbing::*;\nuse super::*;\nuse rayon_core::join;\nuse std::iter;\n\n/// `Chain` is an iterator that joins `b` after `a` in one continuous iterator.\n/// This struct is created by the [`chain()`] method on [`ParallelIterator`]\n///\n/// [`chain()`]: ParallelIterator::chain()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\npub struct Chain<A, B> {\n    a: A,\n    b: B,\n}\n\nimpl<A, B> Chain<A, B> {\n    /// Creates a new `Chain` iterator.\n    pub(super) fn new(a: A, b: B) -> Self {\n        Chain { a, b }\n    }\n}\n\nimpl<A, B> ParallelIterator for Chain<A, B>\nwhere\n    A: ParallelIterator,\n    B: ParallelIterator<Item = A::Item>,\n{\n    type Item = A::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let Chain { a, b } = self;\n\n        // If we returned a value from our own `opt_len`, then the collect consumer in particular\n        // will balk at being treated like an actual `UnindexedConsumer`.  But when we do know the\n        // length, we can use `Consumer::split_at` instead, and this is still harmless for other\n        // truly-unindexed consumers too.\n        let (left, right, reducer) = if let Some(len) = a.opt_len() {\n            consumer.split_at(len)\n        } else {\n            let reducer = consumer.to_reducer();\n            (consumer.split_off_left(), consumer, reducer)\n        };\n\n        let (a, b) = join(|| a.drive_unindexed(left), || b.drive_unindexed(right));\n        reducer.reduce(a, b)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        self.a.opt_len()?.checked_add(self.b.opt_len()?)\n    }\n}\n\nimpl<A, B> IndexedParallelIterator for Chain<A, B>\nwhere\n    A: IndexedParallelIterator,\n    B: IndexedParallelIterator<Item = A::Item>,\n{\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        let Chain { a, b } = self;\n        let (left, right, reducer) = consumer.split_at(a.len());\n        let (a, b) = join(|| a.drive(left), || b.drive(right));\n        reducer.reduce(a, b)\n    }\n\n    fn len(&self) -> usize {\n        self.a.len().checked_add(self.b.len()).expect(\"overflow\")\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        let a_len = self.a.len();\n        return self.a.with_producer(CallbackA {\n            callback,\n            a_len,\n            b: self.b,\n        });\n\n        struct CallbackA<CB, B> {\n            callback: CB,\n            a_len: usize,\n            b: B,\n        }\n\n        impl<CB, B> ProducerCallback<B::Item> for CallbackA<CB, B>\n        where\n            B: IndexedParallelIterator,\n            CB: ProducerCallback<B::Item>,\n        {\n            type Output = CB::Output;\n\n            fn callback<A>(self, a_producer: A) -> Self::Output\n            where\n                A: Producer<Item = B::Item>,\n            {\n                self.b.with_producer(CallbackB {\n                    callback: self.callback,\n                    a_len: self.a_len,\n                    a_producer,\n                })\n            }\n        }\n\n        struct CallbackB<CB, A> {\n            callback: CB,\n            a_len: usize,\n            a_producer: A,\n        }\n\n        impl<CB, A> ProducerCallback<A::Item> for CallbackB<CB, A>\n        where\n            A: Producer,\n            CB: ProducerCallback<A::Item>,\n        {\n            type Output = CB::Output;\n\n            fn callback<B>(self, b_producer: B) -> Self::Output\n            where\n                B: Producer<Item = A::Item>,\n            {\n                let producer = ChainProducer::new(self.a_len, self.a_producer, b_producer);\n                self.callback.callback(producer)\n            }\n        }\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n\nstruct ChainProducer<A, B>\nwhere\n    A: Producer,\n    B: Producer<Item = A::Item>,\n{\n    a_len: usize,\n    a: A,\n    b: B,\n}\n\nimpl<A, B> ChainProducer<A, B>\nwhere\n    A: Producer,\n    B: Producer<Item = A::Item>,\n{\n    fn new(a_len: usize, a: A, b: B) -> Self {\n        ChainProducer { a_len, a, b }\n    }\n}\n\nimpl<A, B> Producer for ChainProducer<A, B>\nwhere\n    A: Producer,\n    B: Producer<Item = A::Item>,\n{\n    type Item = A::Item;\n    type IntoIter = ChainSeq<A::IntoIter, B::IntoIter>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        ChainSeq::new(self.a.into_iter(), self.b.into_iter())\n    }\n\n    fn min_len(&self) -> usize {\n        Ord::max(self.a.min_len(), self.b.min_len())\n    }\n\n    fn max_len(&self) -> usize {\n        Ord::min(self.a.max_len(), self.b.max_len())\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        if index <= self.a_len {\n            let a_rem = self.a_len - index;\n            let (a_left, a_right) = self.a.split_at(index);\n            let (b_left, b_right) = self.b.split_at(0);\n            (\n                ChainProducer::new(index, a_left, b_left),\n                ChainProducer::new(a_rem, a_right, b_right),\n            )\n        } else {\n            let (a_left, a_right) = self.a.split_at(self.a_len);\n            let (b_left, b_right) = self.b.split_at(index - self.a_len);\n            (\n                ChainProducer::new(self.a_len, a_left, b_left),\n                ChainProducer::new(0, a_right, b_right),\n            )\n        }\n    }\n\n    fn fold_with<F>(self, mut folder: F) -> F\n    where\n        F: Folder<A::Item>,\n    {\n        folder = self.a.fold_with(folder);\n        if folder.full() {\n            folder\n        } else {\n            self.b.fold_with(folder)\n        }\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n\n/// Wrapper for `Chain` to implement `ExactSizeIterator`\nstruct ChainSeq<A, B> {\n    chain: iter::Chain<A, B>,\n}\n\nimpl<A, B> ChainSeq<A, B> {\n    fn new(a: A, b: B) -> ChainSeq<A, B>\n    where\n        A: ExactSizeIterator,\n        B: ExactSizeIterator<Item = A::Item>,\n    {\n        ChainSeq { chain: a.chain(b) }\n    }\n}\n\nimpl<A, B> Iterator for ChainSeq<A, B>\nwhere\n    A: Iterator,\n    B: Iterator<Item = A::Item>,\n{\n    type Item = A::Item;\n\n    fn next(&mut self) -> Option<Self::Item> {\n        self.chain.next()\n    }\n\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        self.chain.size_hint()\n    }\n}\n\nimpl<A, B> ExactSizeIterator for ChainSeq<A, B>\nwhere\n    A: ExactSizeIterator,\n    B: ExactSizeIterator<Item = A::Item>,\n{\n}\n\nimpl<A, B> DoubleEndedIterator for ChainSeq<A, B>\nwhere\n    A: DoubleEndedIterator,\n    B: DoubleEndedIterator<Item = A::Item>,\n{\n    fn next_back(&mut self) -> Option<Self::Item> {\n        self.chain.next_back()\n    }\n}\n"
  },
  {
    "path": "src/iter/chunks.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\n/// `Chunks` is an iterator that groups elements of an underlying iterator.\n///\n/// This struct is created by the [`chunks()`] method on [`IndexedParallelIterator`]\n///\n/// [`chunks()`]: IndexedParallelIterator::chunks()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\npub struct Chunks<I> {\n    size: usize,\n    i: I,\n}\n\nimpl<I> Chunks<I> {\n    /// Creates a new `Chunks` iterator\n    pub(super) fn new(i: I, size: usize) -> Self {\n        Chunks { i, size }\n    }\n}\n\nimpl<I> ParallelIterator for Chunks<I>\nwhere\n    I: IndexedParallelIterator,\n{\n    type Item = Vec<I::Item>;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Vec<I::Item>>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<I> IndexedParallelIterator for Chunks<I>\nwhere\n    I: IndexedParallelIterator,\n{\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.i.len().div_ceil(self.size)\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        let len = self.i.len();\n        return self.i.with_producer(Callback {\n            size: self.size,\n            len,\n            callback,\n        });\n\n        struct Callback<CB> {\n            size: usize,\n            len: usize,\n            callback: CB,\n        }\n\n        impl<T, CB> ProducerCallback<T> for Callback<CB>\n        where\n            CB: ProducerCallback<Vec<T>>,\n        {\n            type Output = CB::Output;\n\n            fn callback<P>(self, base: P) -> CB::Output\n            where\n                P: Producer<Item = T>,\n            {\n                let producer = ChunkProducer::new(self.size, self.len, base, Vec::from_iter);\n                self.callback.callback(producer)\n            }\n        }\n    }\n}\n\npub(super) struct ChunkProducer<P, F> {\n    chunk_size: usize,\n    len: usize,\n    base: P,\n    map: F,\n}\n\nimpl<P, F> ChunkProducer<P, F> {\n    pub(super) fn new(chunk_size: usize, len: usize, base: P, map: F) -> Self {\n        Self {\n            chunk_size,\n            len,\n            base,\n            map,\n        }\n    }\n}\n\nimpl<P, F, T> Producer for ChunkProducer<P, F>\nwhere\n    P: Producer,\n    F: Fn(P::IntoIter) -> T + Send + Clone,\n{\n    type Item = T;\n    type IntoIter = std::iter::Map<ChunkSeq<P>, F>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        let chunks = ChunkSeq {\n            chunk_size: self.chunk_size,\n            len: self.len,\n            inner: if self.len > 0 { Some(self.base) } else { None },\n        };\n        chunks.map(self.map)\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let elem_index = Ord::min(index * self.chunk_size, self.len);\n        let (left, right) = self.base.split_at(elem_index);\n        (\n            ChunkProducer {\n                chunk_size: self.chunk_size,\n                len: elem_index,\n                base: left,\n                map: self.map.clone(),\n            },\n            ChunkProducer {\n                chunk_size: self.chunk_size,\n                len: self.len - elem_index,\n                base: right,\n                map: self.map,\n            },\n        )\n    }\n\n    fn min_len(&self) -> usize {\n        self.base.min_len().div_ceil(self.chunk_size)\n    }\n\n    fn max_len(&self) -> usize {\n        self.base.max_len() / self.chunk_size\n    }\n}\n\npub(super) struct ChunkSeq<P> {\n    chunk_size: usize,\n    len: usize,\n    inner: Option<P>,\n}\n\nimpl<P> Iterator for ChunkSeq<P>\nwhere\n    P: Producer,\n{\n    type Item = P::IntoIter;\n\n    fn next(&mut self) -> Option<Self::Item> {\n        let producer = self.inner.take()?;\n        if self.len > self.chunk_size {\n            let (left, right) = producer.split_at(self.chunk_size);\n            self.inner = Some(right);\n            self.len -= self.chunk_size;\n            Some(left.into_iter())\n        } else {\n            debug_assert!(self.len > 0);\n            self.len = 0;\n            Some(producer.into_iter())\n        }\n    }\n\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        let len = self.len();\n        (len, Some(len))\n    }\n}\n\nimpl<P> ExactSizeIterator for ChunkSeq<P>\nwhere\n    P: Producer,\n{\n    #[inline]\n    fn len(&self) -> usize {\n        self.len.div_ceil(self.chunk_size)\n    }\n}\n\nimpl<P> DoubleEndedIterator for ChunkSeq<P>\nwhere\n    P: Producer,\n{\n    fn next_back(&mut self) -> Option<Self::Item> {\n        let producer = self.inner.take()?;\n        if self.len > self.chunk_size {\n            let mut size = self.len % self.chunk_size;\n            if size == 0 {\n                size = self.chunk_size;\n            }\n            let (left, right) = producer.split_at(self.len - size);\n            self.inner = Some(left);\n            self.len -= size;\n            Some(right.into_iter())\n        } else {\n            debug_assert!(self.len > 0);\n            self.len = 0;\n            Some(producer.into_iter())\n        }\n    }\n}\n"
  },
  {
    "path": "src/iter/cloned.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\nuse std::iter;\n\n/// `Cloned` is an iterator that clones the elements of an underlying iterator.\n///\n/// This struct is created by the [`cloned()`] method on [`ParallelIterator`]\n///\n/// [`cloned()`]: ParallelIterator::cloned()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\npub struct Cloned<I> {\n    base: I,\n}\n\nimpl<I> Cloned<I> {\n    /// Creates a new `Cloned` iterator.\n    pub(super) fn new(base: I) -> Self {\n        Cloned { base }\n    }\n}\n\nimpl<'a, T, I> ParallelIterator for Cloned<I>\nwhere\n    I: ParallelIterator<Item = &'a T>,\n    T: 'a + Clone + Send + Sync,\n{\n    type Item = T;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer1 = ClonedConsumer::new(consumer);\n        self.base.drive_unindexed(consumer1)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        self.base.opt_len()\n    }\n}\n\nimpl<'a, T, I> IndexedParallelIterator for Cloned<I>\nwhere\n    I: IndexedParallelIterator<Item = &'a T>,\n    T: 'a + Clone + Send + Sync,\n{\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        let consumer1 = ClonedConsumer::new(consumer);\n        self.base.drive(consumer1)\n    }\n\n    fn len(&self) -> usize {\n        self.base.len()\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        return self.base.with_producer(Callback { callback });\n\n        struct Callback<CB> {\n            callback: CB,\n        }\n\n        impl<'a, T, CB> ProducerCallback<&'a T> for Callback<CB>\n        where\n            CB: ProducerCallback<T>,\n            T: 'a + Clone + Send,\n        {\n            type Output = CB::Output;\n\n            fn callback<P>(self, base: P) -> CB::Output\n            where\n                P: Producer<Item = &'a T>,\n            {\n                let producer = ClonedProducer { base };\n                self.callback.callback(producer)\n            }\n        }\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n\nstruct ClonedProducer<P> {\n    base: P,\n}\n\nimpl<'a, T, P> Producer for ClonedProducer<P>\nwhere\n    P: Producer<Item = &'a T>,\n    T: 'a + Clone,\n{\n    type Item = T;\n    type IntoIter = iter::Cloned<P::IntoIter>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.base.into_iter().cloned()\n    }\n\n    fn min_len(&self) -> usize {\n        self.base.min_len()\n    }\n\n    fn max_len(&self) -> usize {\n        self.base.max_len()\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let (left, right) = self.base.split_at(index);\n        (\n            ClonedProducer { base: left },\n            ClonedProducer { base: right },\n        )\n    }\n\n    fn fold_with<F>(self, folder: F) -> F\n    where\n        F: Folder<Self::Item>,\n    {\n        self.base.fold_with(ClonedFolder { base: folder }).base\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Consumer implementation\n\nstruct ClonedConsumer<C> {\n    base: C,\n}\n\nimpl<C> ClonedConsumer<C> {\n    fn new(base: C) -> Self {\n        ClonedConsumer { base }\n    }\n}\n\nimpl<'a, T, C> Consumer<&'a T> for ClonedConsumer<C>\nwhere\n    C: Consumer<T>,\n    T: 'a + Clone,\n{\n    type Folder = ClonedFolder<C::Folder>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            ClonedConsumer::new(left),\n            ClonedConsumer::new(right),\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        ClonedFolder {\n            base: self.base.into_folder(),\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\nimpl<'a, T, C> UnindexedConsumer<&'a T> for ClonedConsumer<C>\nwhere\n    C: UnindexedConsumer<T>,\n    T: 'a + Clone,\n{\n    fn split_off_left(&self) -> Self {\n        ClonedConsumer::new(self.base.split_off_left())\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n\nstruct ClonedFolder<F> {\n    base: F,\n}\n\nimpl<'a, T, F> Folder<&'a T> for ClonedFolder<F>\nwhere\n    F: Folder<T>,\n    T: 'a + Clone,\n{\n    type Result = F::Result;\n\n    fn consume(self, item: &'a T) -> Self {\n        ClonedFolder {\n            base: self.base.consume(item.clone()),\n        }\n    }\n\n    fn consume_iter<I>(mut self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = &'a T>,\n    {\n        self.base = self.base.consume_iter(iter.into_iter().cloned());\n        self\n    }\n\n    fn complete(self) -> F::Result {\n        self.base.complete()\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n"
  },
  {
    "path": "src/iter/collect/consumer.rs",
    "content": "use super::super::plumbing::*;\nuse crate::SendPtr;\nuse std::marker::PhantomData;\nuse std::ptr;\n\npub(super) struct CollectConsumer<'c, T: Send> {\n    /// See `CollectResult` for explanation of why this is not a slice\n    start: SendPtr<T>,\n    len: usize,\n    marker: PhantomData<&'c mut T>,\n}\n\nimpl<T: Send> CollectConsumer<'_, T> {\n    /// Create a collector for `len` items in the unused capacity of the vector.\n    pub(super) fn appender(vec: &mut Vec<T>, len: usize) -> CollectConsumer<'_, T> {\n        let start = vec.len();\n        assert!(vec.capacity() - start >= len);\n\n        // SAFETY: We already made sure to have the additional space allocated.\n        // The pointer is derived from `Vec` directly, not through a `Deref`,\n        // so it has provenance over the whole allocation.\n        unsafe { CollectConsumer::new(vec.as_mut_ptr().add(start), len) }\n    }\n}\n\nimpl<'c, T: Send + 'c> CollectConsumer<'c, T> {\n    /// The target memory is considered uninitialized, and will be\n    /// overwritten without reading or dropping existing values.\n    unsafe fn new(start: *mut T, len: usize) -> Self {\n        CollectConsumer {\n            start: SendPtr(start),\n            len,\n            marker: PhantomData,\n        }\n    }\n}\n\n/// CollectResult represents an initialized part of the target slice.\n///\n/// This is a proxy owner of the elements in the slice; when it drops,\n/// the elements will be dropped, unless its ownership is released before then.\n#[must_use]\npub(super) struct CollectResult<'c, T> {\n    /// This pointer and length has the same representation as a slice,\n    /// but retains the provenance of the entire array so that we can merge\n    /// these regions together in `CollectReducer`.\n    start: SendPtr<T>,\n    total_len: usize,\n    /// The current initialized length after `start`\n    initialized_len: usize,\n    /// Lifetime invariance guarantees that the data flows from consumer to result,\n    /// especially for the `scope_fn` callback in `Collect::with_consumer`.\n    invariant_lifetime: PhantomData<&'c mut &'c mut [T]>,\n}\n\nunsafe impl<'c, T> Send for CollectResult<'c, T> where T: Send {}\n\nimpl<'c, T> CollectResult<'c, T> {\n    /// The current length of the collect result\n    pub(super) fn len(&self) -> usize {\n        self.initialized_len\n    }\n\n    /// Release ownership of the slice of elements, and return the length\n    pub(super) fn release_ownership(mut self) -> usize {\n        let ret = self.initialized_len;\n        self.initialized_len = 0;\n        ret\n    }\n}\n\nimpl<'c, T> Drop for CollectResult<'c, T> {\n    fn drop(&mut self) {\n        // Drop the first `self.initialized_len` elements, which have been recorded\n        // to be initialized by the folder.\n        unsafe {\n            ptr::drop_in_place(ptr::slice_from_raw_parts_mut(\n                self.start.0,\n                self.initialized_len,\n            ));\n        }\n    }\n}\n\nimpl<'c, T: Send + 'c> Consumer<T> for CollectConsumer<'c, T> {\n    type Folder = CollectResult<'c, T>;\n    type Reducer = CollectReducer;\n    type Result = CollectResult<'c, T>;\n\n    fn split_at(self, index: usize) -> (Self, Self, CollectReducer) {\n        let CollectConsumer { start, len, .. } = self;\n\n        // Produce new consumers.\n        // SAFETY: This assert checks that `index` is a valid offset for `start`\n        unsafe {\n            assert!(index <= len);\n            (\n                CollectConsumer::new(start.0, index),\n                CollectConsumer::new(start.0.add(index), len - index),\n                CollectReducer,\n            )\n        }\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        // Create a result/folder that consumes values and writes them\n        // into the region after start. The initial result has length 0.\n        CollectResult {\n            start: self.start,\n            total_len: self.len,\n            initialized_len: 0,\n            invariant_lifetime: PhantomData,\n        }\n    }\n\n    fn full(&self) -> bool {\n        false\n    }\n}\n\nimpl<'c, T: Send + 'c> Folder<T> for CollectResult<'c, T> {\n    type Result = Self;\n\n    fn consume(mut self, item: T) -> Self {\n        assert!(\n            self.initialized_len < self.total_len,\n            \"too many values pushed to consumer\"\n        );\n\n        // SAFETY: The assert above is a bounds check for this write, and we\n        // avoid assignment here so we do not drop an uninitialized T.\n        unsafe {\n            // Write item and increase the initialized length\n            self.start.0.add(self.initialized_len).write(item);\n            self.initialized_len += 1;\n        }\n\n        self\n    }\n\n    fn complete(self) -> Self::Result {\n        // NB: We don't explicitly check that the local writes were complete,\n        // but Collect will assert the total result length in the end.\n        self\n    }\n\n    fn full(&self) -> bool {\n        false\n    }\n}\n\n/// Pretend to be unindexed for `special_collect_into_vec`,\n/// but we should never actually get used that way...\nimpl<'c, T: Send + 'c> UnindexedConsumer<T> for CollectConsumer<'c, T> {\n    fn split_off_left(&self) -> Self {\n        unreachable!(\"CollectConsumer must be indexed!\")\n    }\n    fn to_reducer(&self) -> Self::Reducer {\n        CollectReducer\n    }\n}\n\n/// CollectReducer combines adjacent chunks; the result must always\n/// be contiguous so that it is one combined slice.\npub(super) struct CollectReducer;\n\nimpl<'c, T> Reducer<CollectResult<'c, T>> for CollectReducer {\n    fn reduce(\n        self,\n        mut left: CollectResult<'c, T>,\n        right: CollectResult<'c, T>,\n    ) -> CollectResult<'c, T> {\n        // Merge if the CollectResults are adjacent and in left to right order\n        // else: drop the right piece now and total length will end up short in the end,\n        // when the correctness of the collected result is asserted.\n        unsafe {\n            let left_end = left.start.0.add(left.initialized_len);\n            if left_end == right.start.0 {\n                left.total_len += right.total_len;\n                left.initialized_len += right.release_ownership();\n            }\n            left\n        }\n    }\n}\n"
  },
  {
    "path": "src/iter/collect/mod.rs",
    "content": "use super::{IndexedParallelIterator, ParallelIterator};\n\nmod consumer;\nuse self::consumer::CollectConsumer;\nuse self::consumer::CollectResult;\nuse super::unzip::unzip_indexed;\n\nmod test;\n\n/// Collects the results of the exact iterator into the specified vector.\n///\n/// This is called by `IndexedParallelIterator::collect_into_vec`.\npub(super) fn collect_into_vec<I, T>(pi: I, v: &mut Vec<T>)\nwhere\n    I: IndexedParallelIterator<Item = T>,\n    T: Send,\n{\n    v.truncate(0); // clear any old data\n    let len = pi.len();\n    collect_with_consumer(v, len, |consumer| pi.drive(consumer));\n}\n\n/// Collects the results of the iterator into the specified vector.\n///\n/// Technically, this only works for `IndexedParallelIterator`, but we're faking a\n/// bit of specialization here until Rust can do that natively.  Callers are\n/// using `opt_len` to find the length before calling this, and only exact\n/// iterators will return anything but `None` there.\n///\n/// Since the type system doesn't understand that contract, we have to allow\n/// *any* `ParallelIterator` here, and `CollectConsumer` has to also implement\n/// `UnindexedConsumer`.  That implementation panics `unreachable!` in case\n/// there's a bug where we actually do try to use this unindexed.\npub(super) fn special_extend<I, T>(pi: I, len: usize, v: &mut Vec<T>)\nwhere\n    I: ParallelIterator<Item = T>,\n    T: Send,\n{\n    collect_with_consumer(v, len, |consumer| pi.drive_unindexed(consumer));\n}\n\n/// Unzips the results of the exact iterator into the specified vectors.\n///\n/// This is called by `IndexedParallelIterator::unzip_into_vecs`.\npub(super) fn unzip_into_vecs<I, A, B>(pi: I, left: &mut Vec<A>, right: &mut Vec<B>)\nwhere\n    I: IndexedParallelIterator<Item = (A, B)>,\n    A: Send,\n    B: Send,\n{\n    // clear any old data\n    left.truncate(0);\n    right.truncate(0);\n\n    let len = pi.len();\n    collect_with_consumer(right, len, |right_consumer| {\n        let mut right_result = None;\n        collect_with_consumer(left, len, |left_consumer| {\n            let (left_r, right_r) = unzip_indexed(pi, left_consumer, right_consumer);\n            right_result = Some(right_r);\n            left_r\n        });\n        right_result.unwrap()\n    });\n}\n\n/// Create a consumer on the slice of memory we are collecting into.\n///\n/// The consumer needs to be used inside the scope function, and the\n/// complete collect result passed back.\n///\n/// This method will verify the collect result, and panic if the slice\n/// was not fully written into. Otherwise, in the successful case,\n/// the vector is complete with the collected result.\nfn collect_with_consumer<T, F>(vec: &mut Vec<T>, len: usize, scope_fn: F)\nwhere\n    T: Send,\n    F: FnOnce(CollectConsumer<'_, T>) -> CollectResult<'_, T>,\n{\n    // Reserve space for `len` more elements in the vector,\n    vec.reserve(len);\n\n    // Create the consumer and run the callback for collection.\n    let result = scope_fn(CollectConsumer::appender(vec, len));\n\n    // The `CollectResult` represents a contiguous part of the slice, that has\n    // been written to. On unwind here, the `CollectResult` will be dropped. If\n    // some producers on the way did not produce enough elements, partial\n    // `CollectResult`s may have been dropped without being reduced to the final\n    // result, and we will see that as the length coming up short.\n    //\n    // Here, we assert that added length is fully initialized. This is checked\n    // by the following assert, which verifies if a complete `CollectResult`\n    // was produced; if the length is correct, it is necessarily covering the\n    // target slice. Since we know that the consumer cannot have escaped from\n    // `drive` (by parametricity, essentially), we know that any stores that\n    // will happen, have happened. Unless some code is buggy, that means we\n    // should have seen `len` total writes.\n    let actual_writes = result.len();\n    assert!(\n        actual_writes == len,\n        \"expected {len} total writes, but got {actual_writes}\"\n    );\n\n    // Release the result's mutable borrow and \"proxy ownership\"\n    // of the elements, before the vector takes it over.\n    result.release_ownership();\n\n    let new_len = vec.len() + len;\n\n    unsafe {\n        vec.set_len(new_len);\n    }\n}\n"
  },
  {
    "path": "src/iter/collect/test.rs",
    "content": "#![cfg(test)]\n#![allow(unused_assignments)]\n\n// These tests are primarily targeting \"abusive\" producers that will\n// try to drive the \"collect consumer\" incorrectly. These should\n// result in panics.\n\nuse super::collect_with_consumer;\nuse crate::iter::plumbing::*;\nuse rayon_core::join;\n\nuse std::fmt;\nuse std::panic;\nuse std::sync::atomic::{AtomicUsize, Ordering};\nuse std::thread::Result as ThreadResult;\n\n/// Promises to produce 2 items, but then produces 3.  Does not do any\n/// splits at all.\n#[test]\n#[should_panic(expected = \"too many values\")]\nfn produce_too_many_items() {\n    let mut v = vec![];\n    collect_with_consumer(&mut v, 2, |consumer| {\n        let mut folder = consumer.into_folder();\n        folder = folder.consume(22);\n        folder = folder.consume(23);\n        folder = folder.consume(24);\n        unreachable!(\"folder does not complete\")\n    });\n}\n\n/// Produces fewer items than promised. Does not do any\n/// splits at all.\n#[test]\n#[should_panic(expected = \"expected 5 total writes, but got 2\")]\nfn produce_fewer_items() {\n    let mut v = vec![];\n    collect_with_consumer(&mut v, 5, |consumer| {\n        let mut folder = consumer.into_folder();\n        folder = folder.consume(22);\n        folder = folder.consume(23);\n        folder.complete()\n    });\n}\n\n// Complete is not called by the consumer. Hence,the collection vector is not fully initialized.\n#[test]\n#[should_panic(expected = \"expected 4 total writes, but got 2\")]\nfn left_produces_items_with_no_complete() {\n    let mut v = vec![];\n    collect_with_consumer(&mut v, 4, |consumer| {\n        let (left_consumer, right_consumer, _) = consumer.split_at(2);\n        let mut left_folder = left_consumer.into_folder();\n        let mut right_folder = right_consumer.into_folder();\n        left_folder = left_folder.consume(0).consume(1);\n        right_folder = right_folder.consume(2).consume(3);\n        right_folder.complete()\n    });\n}\n\n// Complete is not called by the right consumer. Hence,the\n// collection vector is not fully initialized.\n#[test]\n#[should_panic(expected = \"expected 4 total writes, but got 2\")]\nfn right_produces_items_with_no_complete() {\n    let mut v = vec![];\n    collect_with_consumer(&mut v, 4, |consumer| {\n        let (left_consumer, right_consumer, _) = consumer.split_at(2);\n        let mut left_folder = left_consumer.into_folder();\n        let mut right_folder = right_consumer.into_folder();\n        left_folder = left_folder.consume(0).consume(1);\n        right_folder = right_folder.consume(2).consume(3);\n        left_folder.complete()\n    });\n}\n\n// Complete is not called by the consumer. Hence,the collection vector is not fully initialized.\n#[test]\n#[cfg_attr(not(panic = \"unwind\"), ignore)]\nfn produces_items_with_no_complete() {\n    let counter = DropCounter::default();\n    let mut v = vec![];\n    let panic_result = panic::catch_unwind(panic::AssertUnwindSafe(|| {\n        collect_with_consumer(&mut v, 2, |consumer| {\n            let mut folder = consumer.into_folder();\n            folder = folder.consume(counter.element());\n            folder = folder.consume(counter.element());\n            panic!(\"folder does not complete\");\n        });\n    }));\n    assert!(v.is_empty());\n    assert_is_panic_with_message(&panic_result, \"folder does not complete\");\n    counter.assert_drop_count();\n}\n\n// The left consumer produces too many items while the right\n// consumer produces correct number.\n#[test]\n#[should_panic(expected = \"too many values\")]\nfn left_produces_too_many_items() {\n    let mut v = vec![];\n    collect_with_consumer(&mut v, 4, |consumer| {\n        let (left_consumer, right_consumer, _) = consumer.split_at(2);\n        let mut left_folder = left_consumer.into_folder();\n        let mut right_folder = right_consumer.into_folder();\n        left_folder = left_folder.consume(0).consume(1).consume(2);\n        right_folder = right_folder.consume(2).consume(3);\n        let _ = right_folder.complete();\n        unreachable!(\"folder does not complete\");\n    });\n}\n\n// The right consumer produces too many items while the left\n// consumer produces correct number.\n#[test]\n#[should_panic(expected = \"too many values\")]\nfn right_produces_too_many_items() {\n    let mut v = vec![];\n    collect_with_consumer(&mut v, 4, |consumer| {\n        let (left_consumer, right_consumer, _) = consumer.split_at(2);\n        let mut left_folder = left_consumer.into_folder();\n        let mut right_folder = right_consumer.into_folder();\n        left_folder = left_folder.consume(0).consume(1);\n        right_folder = right_folder.consume(2).consume(3).consume(4);\n        let _ = left_folder.complete();\n        unreachable!(\"folder does not complete\");\n    });\n}\n\n// The left consumer produces fewer items while the right\n// consumer produces correct number.\n#[test]\n#[should_panic(expected = \"expected 4 total writes, but got 1\")]\nfn left_produces_fewer_items() {\n    let mut v = vec![];\n    collect_with_consumer(&mut v, 4, |consumer| {\n        let reducer = consumer.to_reducer();\n        let (left_consumer, right_consumer, _) = consumer.split_at(2);\n        let mut left_folder = left_consumer.into_folder();\n        let mut right_folder = right_consumer.into_folder();\n        left_folder = left_folder.consume(0);\n        right_folder = right_folder.consume(2).consume(3);\n        let left_result = left_folder.complete();\n        let right_result = right_folder.complete();\n        reducer.reduce(left_result, right_result)\n    });\n}\n\n// The left and right consumer produce the correct number but\n// only left result is returned\n#[test]\n#[should_panic(expected = \"expected 4 total writes, but got 2\")]\nfn only_left_result() {\n    let mut v = vec![];\n    collect_with_consumer(&mut v, 4, |consumer| {\n        let (left_consumer, right_consumer, _) = consumer.split_at(2);\n        let mut left_folder = left_consumer.into_folder();\n        let mut right_folder = right_consumer.into_folder();\n        left_folder = left_folder.consume(0).consume(1);\n        right_folder = right_folder.consume(2).consume(3);\n        let left_result = left_folder.complete();\n        let _ = right_folder.complete();\n        left_result\n    });\n}\n\n// The left and right consumer produce the correct number but\n// only right result is returned\n#[test]\n#[should_panic(expected = \"expected 4 total writes, but got 2\")]\nfn only_right_result() {\n    let mut v = vec![];\n    collect_with_consumer(&mut v, 4, |consumer| {\n        let (left_consumer, right_consumer, _) = consumer.split_at(2);\n        let mut left_folder = left_consumer.into_folder();\n        let mut right_folder = right_consumer.into_folder();\n        left_folder = left_folder.consume(0).consume(1);\n        right_folder = right_folder.consume(2).consume(3);\n        let _ = left_folder.complete();\n        right_folder.complete()\n    });\n}\n\n// The left and right consumer produce the correct number but reduce\n// in the wrong order.\n#[test]\n#[should_panic(expected = \"expected 4 total writes, but got 2\")]\nfn reducer_does_not_preserve_order() {\n    let mut v = vec![];\n    collect_with_consumer(&mut v, 4, |consumer| {\n        let reducer = consumer.to_reducer();\n        let (left_consumer, right_consumer, _) = consumer.split_at(2);\n        let mut left_folder = left_consumer.into_folder();\n        let mut right_folder = right_consumer.into_folder();\n        left_folder = left_folder.consume(0).consume(1);\n        right_folder = right_folder.consume(2).consume(3);\n        let left_result = left_folder.complete();\n        let right_result = right_folder.complete();\n        reducer.reduce(right_result, left_result)\n    });\n}\n\n// The right consumer produces fewer items while the left\n// consumer produces correct number.\n#[test]\n#[should_panic(expected = \"expected 4 total writes, but got 3\")]\nfn right_produces_fewer_items() {\n    let mut v = vec![];\n    collect_with_consumer(&mut v, 4, |consumer| {\n        let reducer = consumer.to_reducer();\n        let (left_consumer, right_consumer, _) = consumer.split_at(2);\n        let mut left_folder = left_consumer.into_folder();\n        let mut right_folder = right_consumer.into_folder();\n        left_folder = left_folder.consume(0).consume(1);\n        right_folder = right_folder.consume(2);\n        let left_result = left_folder.complete();\n        let right_result = right_folder.complete();\n        reducer.reduce(left_result, right_result)\n    });\n}\n\n// The left consumer panics and the right stops short, like `panic_fuse()`.\n// We should get the left panic without finishing `collect_with_consumer`.\n#[test]\n#[should_panic(expected = \"left consumer panic\")]\nfn left_panics() {\n    let mut v = vec![];\n    collect_with_consumer(&mut v, 4, |consumer| {\n        let reducer = consumer.to_reducer();\n        let (left_consumer, right_consumer, _) = consumer.split_at(2);\n        let (left_result, right_result) = join(\n            || {\n                let mut left_folder = left_consumer.into_folder();\n                left_folder = left_folder.consume(0);\n                panic!(\"left consumer panic\");\n            },\n            || {\n                let mut right_folder = right_consumer.into_folder();\n                right_folder = right_folder.consume(2);\n                right_folder.complete() // early return\n            },\n        );\n        reducer.reduce(left_result, right_result)\n    });\n    unreachable!();\n}\n\n// The right consumer panics and the left stops short, like `panic_fuse()`.\n// We should get the right panic without finishing `collect_with_consumer`.\n#[test]\n#[should_panic(expected = \"right consumer panic\")]\nfn right_panics() {\n    let mut v = vec![];\n    collect_with_consumer(&mut v, 4, |consumer| {\n        let reducer = consumer.to_reducer();\n        let (left_consumer, right_consumer, _) = consumer.split_at(2);\n        let (left_result, right_result) = join(\n            || {\n                let mut left_folder = left_consumer.into_folder();\n                left_folder = left_folder.consume(0);\n                left_folder.complete() // early return\n            },\n            || {\n                let mut right_folder = right_consumer.into_folder();\n                right_folder = right_folder.consume(2);\n                panic!(\"right consumer panic\");\n            },\n        );\n        reducer.reduce(left_result, right_result)\n    });\n    unreachable!();\n}\n\n// The left consumer produces fewer items while the right\n// consumer produces correct number; check that created elements are dropped\n#[test]\n#[cfg_attr(not(panic = \"unwind\"), ignore)]\nfn left_produces_fewer_items_drops() {\n    let counter = DropCounter::default();\n    let mut v = vec![];\n    let panic_result = panic::catch_unwind(panic::AssertUnwindSafe(|| {\n        collect_with_consumer(&mut v, 4, |consumer| {\n            let reducer = consumer.to_reducer();\n            let (left_consumer, right_consumer, _) = consumer.split_at(2);\n            let mut left_folder = left_consumer.into_folder();\n            let mut right_folder = right_consumer.into_folder();\n            left_folder = left_folder.consume(counter.element());\n            right_folder = right_folder\n                .consume(counter.element())\n                .consume(counter.element());\n            let left_result = left_folder.complete();\n            let right_result = right_folder.complete();\n            reducer.reduce(left_result, right_result)\n        });\n    }));\n    assert!(v.is_empty());\n    assert_is_panic_with_message(&panic_result, \"expected 4 total writes, but got 1\");\n    counter.assert_drop_count();\n}\n\n/// This counter can create elements, and then count and verify\n/// the number of which have actually been dropped again.\n#[derive(Default)]\nstruct DropCounter {\n    created: AtomicUsize,\n    dropped: AtomicUsize,\n}\n\nstruct Element<'a>(&'a AtomicUsize);\n\nimpl DropCounter {\n    fn created(&self) -> usize {\n        self.created.load(Ordering::SeqCst)\n    }\n\n    fn dropped(&self) -> usize {\n        self.dropped.load(Ordering::SeqCst)\n    }\n\n    fn element(&self) -> Element<'_> {\n        self.created.fetch_add(1, Ordering::SeqCst);\n        Element(&self.dropped)\n    }\n\n    fn assert_drop_count(&self) {\n        assert_eq!(\n            self.created(),\n            self.dropped(),\n            \"Expected {} dropped elements, but found {}\",\n            self.created(),\n            self.dropped()\n        );\n    }\n}\n\nimpl<'a> Drop for Element<'a> {\n    fn drop(&mut self) {\n        self.0.fetch_add(1, Ordering::SeqCst);\n    }\n}\n\n/// Assert that the result from catch_unwind is a panic that contains expected message\nfn assert_is_panic_with_message<T>(result: &ThreadResult<T>, expected: &str)\nwhere\n    T: fmt::Debug,\n{\n    match result {\n        Ok(value) => {\n            panic!(\"assertion failure: Expected panic, got successful {value:?}\");\n        }\n        Err(error) => {\n            let message_str = error.downcast_ref::<&'static str>().cloned();\n            let message_string = error.downcast_ref::<String>().map(String::as_str);\n            if let Some(message) = message_str.or(message_string) {\n                if !message.contains(expected) {\n                    panic!(\n                        \"assertion failure: Expected {expected:?}, but found panic with {message:?}\"\n                    );\n                }\n            // assertion passes\n            } else {\n                panic!(\n                    \"assertion failure: Expected {expected:?}, but found panic with unknown value\"\n                );\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/iter/copied.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\nuse std::iter;\n\n/// `Copied` is an iterator that copies the elements of an underlying iterator.\n///\n/// This struct is created by the [`copied()`] method on [`ParallelIterator`]\n///\n/// [`copied()`]: ParallelIterator::copied()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\npub struct Copied<I> {\n    base: I,\n}\n\nimpl<I> Copied<I> {\n    /// Creates a new `Copied` iterator.\n    pub(super) fn new(base: I) -> Self {\n        Copied { base }\n    }\n}\n\nimpl<'a, T, I> ParallelIterator for Copied<I>\nwhere\n    I: ParallelIterator<Item = &'a T>,\n    T: 'a + Copy + Send + Sync,\n{\n    type Item = T;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer1 = CopiedConsumer::new(consumer);\n        self.base.drive_unindexed(consumer1)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        self.base.opt_len()\n    }\n}\n\nimpl<'a, T, I> IndexedParallelIterator for Copied<I>\nwhere\n    I: IndexedParallelIterator<Item = &'a T>,\n    T: 'a + Copy + Send + Sync,\n{\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        let consumer1 = CopiedConsumer::new(consumer);\n        self.base.drive(consumer1)\n    }\n\n    fn len(&self) -> usize {\n        self.base.len()\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        return self.base.with_producer(Callback { callback });\n\n        struct Callback<CB> {\n            callback: CB,\n        }\n\n        impl<'a, T, CB> ProducerCallback<&'a T> for Callback<CB>\n        where\n            CB: ProducerCallback<T>,\n            T: 'a + Copy + Send,\n        {\n            type Output = CB::Output;\n\n            fn callback<P>(self, base: P) -> CB::Output\n            where\n                P: Producer<Item = &'a T>,\n            {\n                let producer = CopiedProducer { base };\n                self.callback.callback(producer)\n            }\n        }\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n\nstruct CopiedProducer<P> {\n    base: P,\n}\n\nimpl<'a, T, P> Producer for CopiedProducer<P>\nwhere\n    P: Producer<Item = &'a T>,\n    T: 'a + Copy,\n{\n    type Item = T;\n    type IntoIter = iter::Copied<P::IntoIter>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.base.into_iter().copied()\n    }\n\n    fn min_len(&self) -> usize {\n        self.base.min_len()\n    }\n\n    fn max_len(&self) -> usize {\n        self.base.max_len()\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let (left, right) = self.base.split_at(index);\n        (\n            CopiedProducer { base: left },\n            CopiedProducer { base: right },\n        )\n    }\n\n    fn fold_with<F>(self, folder: F) -> F\n    where\n        F: Folder<Self::Item>,\n    {\n        self.base.fold_with(CopiedFolder { base: folder }).base\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Consumer implementation\n\nstruct CopiedConsumer<C> {\n    base: C,\n}\n\nimpl<C> CopiedConsumer<C> {\n    fn new(base: C) -> Self {\n        CopiedConsumer { base }\n    }\n}\n\nimpl<'a, T, C> Consumer<&'a T> for CopiedConsumer<C>\nwhere\n    C: Consumer<T>,\n    T: 'a + Copy,\n{\n    type Folder = CopiedFolder<C::Folder>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            CopiedConsumer::new(left),\n            CopiedConsumer::new(right),\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        CopiedFolder {\n            base: self.base.into_folder(),\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\nimpl<'a, T, C> UnindexedConsumer<&'a T> for CopiedConsumer<C>\nwhere\n    C: UnindexedConsumer<T>,\n    T: 'a + Copy,\n{\n    fn split_off_left(&self) -> Self {\n        CopiedConsumer::new(self.base.split_off_left())\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n\nstruct CopiedFolder<F> {\n    base: F,\n}\n\nimpl<'a, T, F> Folder<&'a T> for CopiedFolder<F>\nwhere\n    F: Folder<T>,\n    T: 'a + Copy,\n{\n    type Result = F::Result;\n\n    fn consume(self, &item: &'a T) -> Self {\n        CopiedFolder {\n            base: self.base.consume(item),\n        }\n    }\n\n    fn consume_iter<I>(mut self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = &'a T>,\n    {\n        self.base = self.base.consume_iter(iter.into_iter().copied());\n        self\n    }\n\n    fn complete(self) -> F::Result {\n        self.base.complete()\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n"
  },
  {
    "path": "src/iter/empty.rs",
    "content": "use crate::iter::plumbing::*;\nuse crate::iter::*;\n\nuse std::fmt;\nuse std::marker::PhantomData;\n\n/// Creates a parallel iterator that produces nothing.\n///\n/// This admits no parallelism on its own, but it could be used for code that\n/// deals with generic parallel iterators.\n///\n/// # Examples\n///\n/// ```\n/// use rayon::prelude::*;\n/// use rayon::iter::empty;\n///\n/// let pi = (0..1234).into_par_iter()\n///     .chain(empty())\n///     .chain(1234..10_000);\n///\n/// assert_eq!(pi.count(), 10_000);\n/// ```\npub fn empty<T: Send>() -> Empty<T> {\n    Empty {\n        marker: PhantomData,\n    }\n}\n\n/// Iterator adaptor for [the `empty()` function].\n///\n/// [the `empty()` function]: empty()\npub struct Empty<T> {\n    marker: PhantomData<T>,\n}\n\nimpl<T> Clone for Empty<T> {\n    fn clone(&self) -> Self {\n        Empty {\n            marker: PhantomData,\n        }\n    }\n}\n\nimpl<T: Send> fmt::Debug for Empty<T> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.pad(\"Empty\")\n    }\n}\n\nimpl<T: Send> ParallelIterator for Empty<T> {\n    type Item = T;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        self.drive(consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(0)\n    }\n}\n\nimpl<T: Send> IndexedParallelIterator for Empty<T> {\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        consumer.into_folder().complete()\n    }\n\n    fn len(&self) -> usize {\n        0\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        callback.callback(EmptyProducer(PhantomData))\n    }\n}\n\n/// Private empty producer\nstruct EmptyProducer<T: Send>(PhantomData<T>);\n\nimpl<T: Send> Producer for EmptyProducer<T> {\n    type Item = T;\n    type IntoIter = std::iter::Empty<T>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        std::iter::empty()\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        debug_assert_eq!(index, 0);\n        (self, EmptyProducer(PhantomData))\n    }\n\n    fn fold_with<F>(self, folder: F) -> F\n    where\n        F: Folder<Self::Item>,\n    {\n        folder\n    }\n}\n"
  },
  {
    "path": "src/iter/enumerate.rs",
    "content": "use super::plumbing::*;\nuse super::*;\nuse std::iter;\nuse std::ops::Range;\n\n/// `Enumerate` is an iterator that returns the current count along with the element.\n/// This struct is created by the [`enumerate()`] method on [`IndexedParallelIterator`]\n///\n/// [`enumerate()`]: IndexedParallelIterator::enumerate()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\npub struct Enumerate<I> {\n    base: I,\n}\n\nimpl<I> Enumerate<I> {\n    /// Creates a new `Enumerate` iterator.\n    pub(super) fn new(base: I) -> Self {\n        Enumerate { base }\n    }\n}\n\nimpl<I> ParallelIterator for Enumerate<I>\nwhere\n    I: IndexedParallelIterator,\n{\n    type Item = (usize, I::Item);\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<I> IndexedParallelIterator for Enumerate<I>\nwhere\n    I: IndexedParallelIterator,\n{\n    fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.base.len()\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        return self.base.with_producer(Callback { callback });\n\n        struct Callback<CB> {\n            callback: CB,\n        }\n\n        impl<I, CB> ProducerCallback<I> for Callback<CB>\n        where\n            CB: ProducerCallback<(usize, I)>,\n        {\n            type Output = CB::Output;\n            fn callback<P>(self, base: P) -> CB::Output\n            where\n                P: Producer<Item = I>,\n            {\n                let producer = EnumerateProducer { base, offset: 0 };\n                self.callback.callback(producer)\n            }\n        }\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Producer implementation\n\nstruct EnumerateProducer<P> {\n    base: P,\n    offset: usize,\n}\n\nimpl<P> Producer for EnumerateProducer<P>\nwhere\n    P: Producer,\n{\n    type Item = (usize, P::Item);\n    type IntoIter = iter::Zip<Range<usize>, P::IntoIter>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        // Enumerate only works for IndexedParallelIterators. Since those\n        // have a max length of usize::MAX, their max index is\n        // usize::MAX - 1, so the range 0..usize::MAX includes all\n        // possible indices.\n        //\n        // However, we should to use a precise end to the range, otherwise\n        // reversing the iterator may have to walk back a long ways before\n        // `Zip::next_back` can produce anything.\n        let base = self.base.into_iter();\n        let end = self.offset + base.len();\n        (self.offset..end).zip(base)\n    }\n\n    fn min_len(&self) -> usize {\n        self.base.min_len()\n    }\n    fn max_len(&self) -> usize {\n        self.base.max_len()\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let (left, right) = self.base.split_at(index);\n        (\n            EnumerateProducer {\n                base: left,\n                offset: self.offset,\n            },\n            EnumerateProducer {\n                base: right,\n                offset: self.offset + index,\n            },\n        )\n    }\n}\n"
  },
  {
    "path": "src/iter/extend.rs",
    "content": "use super::noop::NoopConsumer;\nuse super::plumbing::{Consumer, Folder, Reducer, UnindexedConsumer};\nuse super::{IntoParallelIterator, ParallelExtend, ParallelIterator};\n\nuse either::Either;\nuse std::borrow::Cow;\nuse std::collections::LinkedList;\nuse std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};\nuse std::collections::{BinaryHeap, VecDeque};\nuse std::ffi::{OsStr, OsString};\nuse std::hash::{BuildHasher, Hash};\n\n/// Performs a generic `par_extend` by collecting to a `LinkedList<Vec<_>>` in\n/// parallel, then extending the collection sequentially.\nmacro_rules! extend {\n    ($self:ident, $par_iter:ident) => {\n        extend!($self <- fast_collect($par_iter))\n    };\n    ($self:ident <- $vecs:expr) => {\n        match $vecs {\n            Either::Left(vec) => $self.extend(vec),\n            Either::Right(list) => {\n                for vec in list {\n                    $self.extend(vec);\n                }\n            }\n        }\n    };\n}\nmacro_rules! extend_reserved {\n    ($self:ident, $par_iter:ident, $len:ident) => {\n        let vecs = fast_collect($par_iter);\n        $self.reserve($len(&vecs));\n        extend!($self <- vecs)\n    };\n    ($self:ident, $par_iter:ident) => {\n        extend_reserved!($self, $par_iter, len)\n    };\n}\n\n/// Computes the total length of a `fast_collect` result.\nfn len<T>(vecs: &Either<Vec<T>, LinkedList<Vec<T>>>) -> usize {\n    match vecs {\n        Either::Left(vec) => vec.len(),\n        Either::Right(list) => list.iter().map(Vec::len).sum(),\n    }\n}\n\n/// Computes the total string length of a `fast_collect` result.\nfn string_len<T: AsRef<str>>(vecs: &Either<Vec<T>, LinkedList<Vec<T>>>) -> usize {\n    let strs = match vecs {\n        Either::Left(vec) => Either::Left(vec.iter()),\n        Either::Right(list) => Either::Right(list.iter().flatten()),\n    };\n    strs.map(AsRef::as_ref).map(str::len).sum()\n}\n\n/// Computes the total OS-string length of a `fast_collect` result.\nfn osstring_len<T: AsRef<OsStr>>(vecs: &Either<Vec<T>, LinkedList<Vec<T>>>) -> usize {\n    let osstrs = match vecs {\n        Either::Left(vec) => Either::Left(vec.iter()),\n        Either::Right(list) => Either::Right(list.iter().flatten()),\n    };\n    osstrs.map(AsRef::as_ref).map(OsStr::len).sum()\n}\n\npub(super) fn fast_collect<I, T>(pi: I) -> Either<Vec<T>, LinkedList<Vec<T>>>\nwhere\n    I: IntoParallelIterator<Item = T>,\n    T: Send,\n{\n    let par_iter = pi.into_par_iter();\n    match par_iter.opt_len() {\n        Some(len) => {\n            // Pseudo-specialization. See impl of ParallelExtend for Vec for more details.\n            let mut vec = Vec::new();\n            super::collect::special_extend(par_iter, len, &mut vec);\n            Either::Left(vec)\n        }\n        None => Either::Right(par_iter.drive_unindexed(ListVecConsumer)),\n    }\n}\n\nstruct ListVecConsumer;\n\nstruct ListVecFolder<T> {\n    vec: Vec<T>,\n}\n\nimpl<T: Send> Consumer<T> for ListVecConsumer {\n    type Folder = ListVecFolder<T>;\n    type Reducer = ListReducer;\n    type Result = LinkedList<Vec<T>>;\n\n    fn split_at(self, _index: usize) -> (Self, Self, Self::Reducer) {\n        (Self, Self, ListReducer)\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        ListVecFolder { vec: Vec::new() }\n    }\n\n    fn full(&self) -> bool {\n        false\n    }\n}\n\nimpl<T: Send> UnindexedConsumer<T> for ListVecConsumer {\n    fn split_off_left(&self) -> Self {\n        Self\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        ListReducer\n    }\n}\n\nimpl<T> Folder<T> for ListVecFolder<T> {\n    type Result = LinkedList<Vec<T>>;\n\n    fn consume(mut self, item: T) -> Self {\n        self.vec.push(item);\n        self\n    }\n\n    fn consume_iter<I>(mut self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = T>,\n    {\n        self.vec.extend(iter);\n        self\n    }\n\n    fn complete(self) -> Self::Result {\n        let mut list = LinkedList::new();\n        if !self.vec.is_empty() {\n            list.push_back(self.vec);\n        }\n        list\n    }\n\n    fn full(&self) -> bool {\n        false\n    }\n}\n\n/// Extends a binary heap with items from a parallel iterator.\nimpl<T> ParallelExtend<T> for BinaryHeap<T>\nwhere\n    T: Ord + Send,\n{\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = T>,\n    {\n        extend_reserved!(self, par_iter);\n    }\n}\n\n/// Extends a binary heap with copied items from a parallel iterator.\nimpl<'a, T> ParallelExtend<&'a T> for BinaryHeap<T>\nwhere\n    T: 'a + Copy + Ord + Send + Sync,\n{\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = &'a T>,\n    {\n        extend_reserved!(self, par_iter);\n    }\n}\n\n/// Extends a B-tree map with items from a parallel iterator.\nimpl<K, V> ParallelExtend<(K, V)> for BTreeMap<K, V>\nwhere\n    K: Ord + Send,\n    V: Send,\n{\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = (K, V)>,\n    {\n        extend!(self, par_iter);\n    }\n}\n\n/// Extends a B-tree map with copied items from a parallel iterator.\nimpl<'a, K: 'a, V: 'a> ParallelExtend<(&'a K, &'a V)> for BTreeMap<K, V>\nwhere\n    K: Copy + Ord + Send + Sync,\n    V: Copy + Send + Sync,\n{\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = (&'a K, &'a V)>,\n    {\n        extend!(self, par_iter);\n    }\n}\n\n/// Extends a B-tree set with items from a parallel iterator.\nimpl<T> ParallelExtend<T> for BTreeSet<T>\nwhere\n    T: Ord + Send,\n{\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = T>,\n    {\n        extend!(self, par_iter);\n    }\n}\n\n/// Extends a B-tree set with copied items from a parallel iterator.\nimpl<'a, T> ParallelExtend<&'a T> for BTreeSet<T>\nwhere\n    T: 'a + Copy + Ord + Send + Sync,\n{\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = &'a T>,\n    {\n        extend!(self, par_iter);\n    }\n}\n\n/// Extends a hash map with items from a parallel iterator.\nimpl<K, V, S> ParallelExtend<(K, V)> for HashMap<K, V, S>\nwhere\n    K: Eq + Hash + Send,\n    V: Send,\n    S: BuildHasher + Send,\n{\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = (K, V)>,\n    {\n        // See the map_collect benchmarks in rayon-demo for different strategies.\n        extend_reserved!(self, par_iter);\n    }\n}\n\n/// Extends a hash map with copied items from a parallel iterator.\nimpl<'a, K: 'a, V: 'a, S> ParallelExtend<(&'a K, &'a V)> for HashMap<K, V, S>\nwhere\n    K: Copy + Eq + Hash + Send + Sync,\n    V: Copy + Send + Sync,\n    S: BuildHasher + Send,\n{\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = (&'a K, &'a V)>,\n    {\n        extend_reserved!(self, par_iter);\n    }\n}\n\n/// Extends a hash set with items from a parallel iterator.\nimpl<T, S> ParallelExtend<T> for HashSet<T, S>\nwhere\n    T: Eq + Hash + Send,\n    S: BuildHasher + Send,\n{\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = T>,\n    {\n        extend_reserved!(self, par_iter);\n    }\n}\n\n/// Extends a hash set with copied items from a parallel iterator.\nimpl<'a, T, S> ParallelExtend<&'a T> for HashSet<T, S>\nwhere\n    T: 'a + Copy + Eq + Hash + Send + Sync,\n    S: BuildHasher + Send,\n{\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = &'a T>,\n    {\n        extend_reserved!(self, par_iter);\n    }\n}\n\n/// Extends a linked list with items from a parallel iterator.\nimpl<T> ParallelExtend<T> for LinkedList<T>\nwhere\n    T: Send,\n{\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = T>,\n    {\n        let mut list = par_iter.into_par_iter().drive_unindexed(ListConsumer);\n        self.append(&mut list);\n    }\n}\n\n/// Extends a linked list with copied items from a parallel iterator.\nimpl<'a, T> ParallelExtend<&'a T> for LinkedList<T>\nwhere\n    T: 'a + Copy + Send + Sync,\n{\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = &'a T>,\n    {\n        self.par_extend(par_iter.into_par_iter().copied())\n    }\n}\n\nstruct ListConsumer;\n\nstruct ListFolder<T> {\n    list: LinkedList<T>,\n}\n\nstruct ListReducer;\n\nimpl<T: Send> Consumer<T> for ListConsumer {\n    type Folder = ListFolder<T>;\n    type Reducer = ListReducer;\n    type Result = LinkedList<T>;\n\n    fn split_at(self, _index: usize) -> (Self, Self, Self::Reducer) {\n        (Self, Self, ListReducer)\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        ListFolder {\n            list: LinkedList::new(),\n        }\n    }\n\n    fn full(&self) -> bool {\n        false\n    }\n}\n\nimpl<T: Send> UnindexedConsumer<T> for ListConsumer {\n    fn split_off_left(&self) -> Self {\n        Self\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        ListReducer\n    }\n}\n\nimpl<T> Folder<T> for ListFolder<T> {\n    type Result = LinkedList<T>;\n\n    fn consume(mut self, item: T) -> Self {\n        self.list.push_back(item);\n        self\n    }\n\n    fn consume_iter<I>(mut self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = T>,\n    {\n        self.list.extend(iter);\n        self\n    }\n\n    fn complete(self) -> Self::Result {\n        self.list\n    }\n\n    fn full(&self) -> bool {\n        false\n    }\n}\n\nimpl<T> Reducer<LinkedList<T>> for ListReducer {\n    fn reduce(self, mut left: LinkedList<T>, mut right: LinkedList<T>) -> LinkedList<T> {\n        left.append(&mut right);\n        left\n    }\n}\n\n/// Extends an OS-string with string slices from a parallel iterator.\nimpl<'a> ParallelExtend<&'a OsStr> for OsString {\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = &'a OsStr>,\n    {\n        extend_reserved!(self, par_iter, osstring_len);\n    }\n}\n\n/// Extends an OS-string with strings from a parallel iterator.\nimpl ParallelExtend<OsString> for OsString {\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = OsString>,\n    {\n        extend_reserved!(self, par_iter, osstring_len);\n    }\n}\n\n/// Extends an OS-string with string slices from a parallel iterator.\nimpl<'a> ParallelExtend<Cow<'a, OsStr>> for OsString {\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = Cow<'a, OsStr>>,\n    {\n        extend_reserved!(self, par_iter, osstring_len);\n    }\n}\n\n/// Extends a string with characters from a parallel iterator.\nimpl ParallelExtend<char> for String {\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = char>,\n    {\n        // This is like `extend`, but `Vec<char>` is less efficient to deal\n        // with than `String`, so instead collect to `LinkedList<String>`.\n        let list = par_iter.into_par_iter().drive_unindexed(ListStringConsumer);\n        self.reserve(list.iter().map(String::len).sum());\n        self.extend(list);\n    }\n}\n\n/// Extends a string with copied characters from a parallel iterator.\nimpl<'a> ParallelExtend<&'a char> for String {\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = &'a char>,\n    {\n        self.par_extend(par_iter.into_par_iter().copied())\n    }\n}\n\nstruct ListStringConsumer;\n\nstruct ListStringFolder {\n    string: String,\n}\n\nimpl Consumer<char> for ListStringConsumer {\n    type Folder = ListStringFolder;\n    type Reducer = ListReducer;\n    type Result = LinkedList<String>;\n\n    fn split_at(self, _index: usize) -> (Self, Self, Self::Reducer) {\n        (Self, Self, ListReducer)\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        ListStringFolder {\n            string: String::new(),\n        }\n    }\n\n    fn full(&self) -> bool {\n        false\n    }\n}\n\nimpl UnindexedConsumer<char> for ListStringConsumer {\n    fn split_off_left(&self) -> Self {\n        Self\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        ListReducer\n    }\n}\n\nimpl Folder<char> for ListStringFolder {\n    type Result = LinkedList<String>;\n\n    fn consume(mut self, item: char) -> Self {\n        self.string.push(item);\n        self\n    }\n\n    fn consume_iter<I>(mut self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = char>,\n    {\n        self.string.extend(iter);\n        self\n    }\n\n    fn complete(self) -> Self::Result {\n        let mut list = LinkedList::new();\n        if !self.string.is_empty() {\n            list.push_back(self.string);\n        }\n        list\n    }\n\n    fn full(&self) -> bool {\n        false\n    }\n}\n\n/// Extends a string with string slices from a parallel iterator.\nimpl<'a> ParallelExtend<&'a str> for String {\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = &'a str>,\n    {\n        extend_reserved!(self, par_iter, string_len);\n    }\n}\n\n/// Extends a string with strings from a parallel iterator.\nimpl ParallelExtend<String> for String {\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = String>,\n    {\n        extend_reserved!(self, par_iter, string_len);\n    }\n}\n\n/// Extends a string with boxed strings from a parallel iterator.\nimpl ParallelExtend<Box<str>> for String {\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = Box<str>>,\n    {\n        extend_reserved!(self, par_iter, string_len);\n    }\n}\n\n/// Extends a string with string slices from a parallel iterator.\nimpl<'a> ParallelExtend<Cow<'a, str>> for String {\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = Cow<'a, str>>,\n    {\n        extend_reserved!(self, par_iter, string_len);\n    }\n}\n\n/// Extends a deque with items from a parallel iterator.\nimpl<T> ParallelExtend<T> for VecDeque<T>\nwhere\n    T: Send,\n{\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = T>,\n    {\n        extend_reserved!(self, par_iter);\n    }\n}\n\n/// Extends a deque with copied items from a parallel iterator.\nimpl<'a, T> ParallelExtend<&'a T> for VecDeque<T>\nwhere\n    T: 'a + Copy + Send + Sync,\n{\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = &'a T>,\n    {\n        extend_reserved!(self, par_iter);\n    }\n}\n\n/// Extends a vector with items from a parallel iterator.\nimpl<T> ParallelExtend<T> for Vec<T>\nwhere\n    T: Send,\n{\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = T>,\n    {\n        // See the vec_collect benchmarks in rayon-demo for different strategies.\n        let par_iter = par_iter.into_par_iter();\n        match par_iter.opt_len() {\n            Some(len) => {\n                // When Rust gets specialization, we can get here for indexed iterators\n                // without relying on `opt_len`.  Until then, `special_extend()` fakes\n                // an unindexed mode on the promise that `opt_len()` is accurate.\n                super::collect::special_extend(par_iter, len, self);\n            }\n            None => {\n                // This works like `extend`, but `Vec::append` is more efficient.\n                let list = par_iter.drive_unindexed(ListVecConsumer);\n                self.reserve(list.iter().map(Vec::len).sum());\n                for mut other in list {\n                    self.append(&mut other);\n                }\n            }\n        }\n    }\n}\n\n/// Extends a vector with copied items from a parallel iterator.\nimpl<'a, T> ParallelExtend<&'a T> for Vec<T>\nwhere\n    T: 'a + Copy + Send + Sync,\n{\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = &'a T>,\n    {\n        self.par_extend(par_iter.into_par_iter().copied())\n    }\n}\n\n/// Collapses all unit items from a parallel iterator into one.\nimpl ParallelExtend<()> for () {\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = ()>,\n    {\n        par_iter.into_par_iter().drive_unindexed(NoopConsumer)\n    }\n}\n"
  },
  {
    "path": "src/iter/filter.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\n\n/// `Filter` takes a predicate `filter_op` and filters out elements that match.\n/// This struct is created by the [`filter()`] method on [`ParallelIterator`]\n///\n/// [`filter()`]: ParallelIterator::filter()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Clone)]\npub struct Filter<I, P> {\n    base: I,\n    filter_op: P,\n}\n\nimpl<I: Debug, P> Debug for Filter<I, P> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"Filter\").field(\"base\", &self.base).finish()\n    }\n}\n\nimpl<I, P> Filter<I, P> {\n    /// Creates a new `Filter` iterator.\n    pub(super) fn new(base: I, filter_op: P) -> Self {\n        Filter { base, filter_op }\n    }\n}\n\nimpl<I, P> ParallelIterator for Filter<I, P>\nwhere\n    I: ParallelIterator,\n    P: Fn(&I::Item) -> bool + Sync + Send,\n{\n    type Item = I::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer1 = FilterConsumer::new(consumer, &self.filter_op);\n        self.base.drive_unindexed(consumer1)\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Consumer implementation\n\nstruct FilterConsumer<'p, C, P> {\n    base: C,\n    filter_op: &'p P,\n}\n\nimpl<'p, C, P> FilterConsumer<'p, C, P> {\n    fn new(base: C, filter_op: &'p P) -> Self {\n        FilterConsumer { base, filter_op }\n    }\n}\n\nimpl<'p, T, C, P: 'p> Consumer<T> for FilterConsumer<'p, C, P>\nwhere\n    C: Consumer<T>,\n    P: Fn(&T) -> bool + Sync,\n{\n    type Folder = FilterFolder<'p, C::Folder, P>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, C::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            FilterConsumer::new(left, self.filter_op),\n            FilterConsumer::new(right, self.filter_op),\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        FilterFolder {\n            base: self.base.into_folder(),\n            filter_op: self.filter_op,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\nimpl<'p, T, C, P: 'p> UnindexedConsumer<T> for FilterConsumer<'p, C, P>\nwhere\n    C: UnindexedConsumer<T>,\n    P: Fn(&T) -> bool + Sync,\n{\n    fn split_off_left(&self) -> Self {\n        FilterConsumer::new(self.base.split_off_left(), self.filter_op)\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n\nstruct FilterFolder<'p, C, P> {\n    base: C,\n    filter_op: &'p P,\n}\n\nimpl<'p, C, P, T> Folder<T> for FilterFolder<'p, C, P>\nwhere\n    C: Folder<T>,\n    P: Fn(&T) -> bool + 'p,\n{\n    type Result = C::Result;\n\n    fn consume(self, item: T) -> Self {\n        let filter_op = self.filter_op;\n        if filter_op(&item) {\n            let base = self.base.consume(item);\n            FilterFolder { base, filter_op }\n        } else {\n            self\n        }\n    }\n\n    // This cannot easily specialize `consume_iter` to be better than\n    // the default, because that requires checking `self.base.full()`\n    // during a call to `self.base.consume_iter()`. (#632)\n\n    fn complete(self) -> Self::Result {\n        self.base.complete()\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n"
  },
  {
    "path": "src/iter/filter_map.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\n\n/// `FilterMap` creates an iterator that uses `filter_op` to both filter and map elements.\n/// This struct is created by the [`filter_map()`] method on [`ParallelIterator`].\n///\n/// [`filter_map()`]: ParallelIterator::filter_map()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Clone)]\npub struct FilterMap<I, P> {\n    base: I,\n    filter_op: P,\n}\n\nimpl<I: Debug, P> Debug for FilterMap<I, P> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"FilterMap\")\n            .field(\"base\", &self.base)\n            .finish()\n    }\n}\n\nimpl<I, P> FilterMap<I, P> {\n    /// Creates a new `FilterMap` iterator.\n    pub(super) fn new(base: I, filter_op: P) -> Self {\n        FilterMap { base, filter_op }\n    }\n}\n\nimpl<I, P, R> ParallelIterator for FilterMap<I, P>\nwhere\n    I: ParallelIterator,\n    P: Fn(I::Item) -> Option<R> + Sync + Send,\n    R: Send,\n{\n    type Item = R;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer = FilterMapConsumer::new(consumer, &self.filter_op);\n        self.base.drive_unindexed(consumer)\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Consumer implementation\n\nstruct FilterMapConsumer<'p, C, P> {\n    base: C,\n    filter_op: &'p P,\n}\n\nimpl<'p, C, P: 'p> FilterMapConsumer<'p, C, P> {\n    fn new(base: C, filter_op: &'p P) -> Self {\n        FilterMapConsumer { base, filter_op }\n    }\n}\n\nimpl<'p, T, U, C, P> Consumer<T> for FilterMapConsumer<'p, C, P>\nwhere\n    C: Consumer<U>,\n    P: Fn(T) -> Option<U> + Sync + 'p,\n{\n    type Folder = FilterMapFolder<'p, C::Folder, P>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            FilterMapConsumer::new(left, self.filter_op),\n            FilterMapConsumer::new(right, self.filter_op),\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        let base = self.base.into_folder();\n        FilterMapFolder {\n            base,\n            filter_op: self.filter_op,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\nimpl<'p, T, U, C, P> UnindexedConsumer<T> for FilterMapConsumer<'p, C, P>\nwhere\n    C: UnindexedConsumer<U>,\n    P: Fn(T) -> Option<U> + Sync + 'p,\n{\n    fn split_off_left(&self) -> Self {\n        FilterMapConsumer::new(self.base.split_off_left(), self.filter_op)\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n\nstruct FilterMapFolder<'p, C, P> {\n    base: C,\n    filter_op: &'p P,\n}\n\nimpl<'p, T, U, C, P> Folder<T> for FilterMapFolder<'p, C, P>\nwhere\n    C: Folder<U>,\n    P: Fn(T) -> Option<U> + Sync + 'p,\n{\n    type Result = C::Result;\n\n    fn consume(self, item: T) -> Self {\n        let filter_op = self.filter_op;\n        if let Some(mapped_item) = filter_op(item) {\n            let base = self.base.consume(mapped_item);\n            FilterMapFolder { base, filter_op }\n        } else {\n            self\n        }\n    }\n\n    // This cannot easily specialize `consume_iter` to be better than\n    // the default, because that requires checking `self.base.full()`\n    // during a call to `self.base.consume_iter()`. (#632)\n\n    fn complete(self) -> C::Result {\n        self.base.complete()\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n"
  },
  {
    "path": "src/iter/find.rs",
    "content": "use super::plumbing::*;\nuse super::*;\nuse std::sync::atomic::{AtomicBool, Ordering};\n\npub(super) fn find<I, P>(pi: I, find_op: P) -> Option<I::Item>\nwhere\n    I: ParallelIterator,\n    P: Fn(&I::Item) -> bool + Sync,\n{\n    let found = AtomicBool::new(false);\n    let consumer = FindConsumer::new(&find_op, &found);\n    pi.drive_unindexed(consumer)\n}\n\nstruct FindConsumer<'p, P> {\n    find_op: &'p P,\n    found: &'p AtomicBool,\n}\n\nimpl<'p, P> FindConsumer<'p, P> {\n    fn new(find_op: &'p P, found: &'p AtomicBool) -> Self {\n        FindConsumer { find_op, found }\n    }\n}\n\nimpl<'p, T, P: 'p> Consumer<T> for FindConsumer<'p, P>\nwhere\n    T: Send,\n    P: Fn(&T) -> bool + Sync,\n{\n    type Folder = FindFolder<'p, T, P>;\n    type Reducer = FindReducer;\n    type Result = Option<T>;\n\n    fn split_at(self, _index: usize) -> (Self, Self, Self::Reducer) {\n        (self.split_off_left(), self, FindReducer)\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        FindFolder {\n            find_op: self.find_op,\n            found: self.found,\n            item: None,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.found.load(Ordering::Relaxed)\n    }\n}\n\nimpl<'p, T, P: 'p> UnindexedConsumer<T> for FindConsumer<'p, P>\nwhere\n    T: Send,\n    P: Fn(&T) -> bool + Sync,\n{\n    fn split_off_left(&self) -> Self {\n        FindConsumer::new(self.find_op, self.found)\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        FindReducer\n    }\n}\n\nstruct FindFolder<'p, T, P> {\n    find_op: &'p P,\n    found: &'p AtomicBool,\n    item: Option<T>,\n}\n\nimpl<'p, T, P> Folder<T> for FindFolder<'p, T, P>\nwhere\n    P: Fn(&T) -> bool + 'p,\n{\n    type Result = Option<T>;\n\n    fn consume(mut self, item: T) -> Self {\n        if (self.find_op)(&item) {\n            self.found.store(true, Ordering::Relaxed);\n            self.item = Some(item);\n        }\n        self\n    }\n\n    fn consume_iter<I>(mut self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = T>,\n    {\n        fn not_full<T>(found: &AtomicBool) -> impl Fn(&T) -> bool + '_ {\n            move |_| !found.load(Ordering::Relaxed)\n        }\n\n        self.item = iter\n            .into_iter()\n            // stop iterating if another thread has found something\n            .take_while(not_full(self.found))\n            .find(self.find_op);\n        if self.item.is_some() {\n            self.found.store(true, Ordering::Relaxed)\n        }\n        self\n    }\n\n    fn complete(self) -> Self::Result {\n        self.item\n    }\n\n    fn full(&self) -> bool {\n        self.found.load(Ordering::Relaxed)\n    }\n}\n\nstruct FindReducer;\n\nimpl<T> Reducer<Option<T>> for FindReducer {\n    fn reduce(self, left: Option<T>, right: Option<T>) -> Option<T> {\n        left.or(right)\n    }\n}\n"
  },
  {
    "path": "src/iter/find_first_last/mod.rs",
    "content": "use super::plumbing::*;\nuse super::*;\nuse std::cell::Cell;\nuse std::sync::atomic::{AtomicUsize, Ordering};\n\n#[cfg(test)]\nmod test;\n\n// The key optimization for find_first is that a consumer can stop its search if\n// some consumer to its left already found a match (and similarly for consumers\n// to the right for find_last). To make this work, all consumers need some\n// notion of their position in the data relative to other consumers, including\n// unindexed consumers that have no built-in notion of position.\n//\n// To solve this, we assign each consumer a lower and upper bound for an\n// imaginary \"range\" of data that it consumes. The initial consumer starts with\n// the range 0..usize::MAX. The split divides this range in half so that\n// one resulting consumer has the range 0..(usize::MAX / 2), and the\n// other has (usize::MAX / 2)..usize::max_value(). Every subsequent\n// split divides the range in half again until it cannot be split anymore\n// (i.e. its length is 1), in which case the split returns two consumers with\n// the same range. In that case both consumers will continue to consume all\n// their data regardless of whether a better match is found, but the reducer\n// will still return the correct answer.\n\n#[derive(Copy, Clone)]\nenum MatchPosition {\n    Leftmost,\n    Rightmost,\n}\n\n/// Returns true if pos1 is a better match than pos2 according to MatchPosition\n#[inline]\nfn better_position(pos1: usize, pos2: usize, mp: MatchPosition) -> bool {\n    match mp {\n        MatchPosition::Leftmost => pos1 < pos2,\n        MatchPosition::Rightmost => pos1 > pos2,\n    }\n}\n\npub(super) fn find_first<I, P>(pi: I, find_op: P) -> Option<I::Item>\nwhere\n    I: ParallelIterator,\n    P: Fn(&I::Item) -> bool + Sync,\n{\n    let best_found = AtomicUsize::new(usize::MAX);\n    let consumer = FindConsumer::new(&find_op, MatchPosition::Leftmost, &best_found);\n    pi.drive_unindexed(consumer)\n}\n\npub(super) fn find_last<I, P>(pi: I, find_op: P) -> Option<I::Item>\nwhere\n    I: ParallelIterator,\n    P: Fn(&I::Item) -> bool + Sync,\n{\n    let best_found = AtomicUsize::new(0);\n    let consumer = FindConsumer::new(&find_op, MatchPosition::Rightmost, &best_found);\n    pi.drive_unindexed(consumer)\n}\n\nstruct FindConsumer<'p, P> {\n    find_op: &'p P,\n    lower_bound: Cell<usize>,\n    upper_bound: usize,\n    match_position: MatchPosition,\n    best_found: &'p AtomicUsize,\n}\n\nimpl<'p, P> FindConsumer<'p, P> {\n    fn new(find_op: &'p P, match_position: MatchPosition, best_found: &'p AtomicUsize) -> Self {\n        FindConsumer {\n            find_op,\n            lower_bound: Cell::new(0),\n            upper_bound: usize::MAX,\n            match_position,\n            best_found,\n        }\n    }\n\n    fn current_index(&self) -> usize {\n        match self.match_position {\n            MatchPosition::Leftmost => self.lower_bound.get(),\n            MatchPosition::Rightmost => self.upper_bound,\n        }\n    }\n}\n\nimpl<'p, T, P> Consumer<T> for FindConsumer<'p, P>\nwhere\n    T: Send,\n    P: Fn(&T) -> bool + Sync,\n{\n    type Folder = FindFolder<'p, T, P>;\n    type Reducer = FindReducer;\n    type Result = Option<T>;\n\n    fn split_at(self, _index: usize) -> (Self, Self, Self::Reducer) {\n        let dir = self.match_position;\n        (\n            self.split_off_left(),\n            self,\n            FindReducer {\n                match_position: dir,\n            },\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        FindFolder {\n            find_op: self.find_op,\n            boundary: self.current_index(),\n            match_position: self.match_position,\n            best_found: self.best_found,\n            item: None,\n        }\n    }\n\n    fn full(&self) -> bool {\n        // can stop consuming if the best found index so far is *strictly*\n        // better than anything this consumer will find\n        better_position(\n            self.best_found.load(Ordering::Relaxed),\n            self.current_index(),\n            self.match_position,\n        )\n    }\n}\n\nimpl<'p, T, P> UnindexedConsumer<T> for FindConsumer<'p, P>\nwhere\n    T: Send,\n    P: Fn(&T) -> bool + Sync,\n{\n    fn split_off_left(&self) -> Self {\n        // Upper bound for one consumer will be lower bound for the other. This\n        // overlap is okay, because only one of the bounds will be used for\n        // comparing against best_found; the other is kept only to be able to\n        // divide the range in half.\n        //\n        // When the resolution of usize has been exhausted (i.e. when\n        // upper_bound = lower_bound), both results of this split will have the\n        // same range. When that happens, we lose the ability to tell one\n        // consumer to stop working when the other finds a better match, but the\n        // reducer ensures that the best answer is still returned (see the test\n        // above).\n        let old_lower_bound = self.lower_bound.get();\n        let median = old_lower_bound + ((self.upper_bound - old_lower_bound) / 2);\n        self.lower_bound.set(median);\n\n        FindConsumer {\n            find_op: self.find_op,\n            lower_bound: Cell::new(old_lower_bound),\n            upper_bound: median,\n            match_position: self.match_position,\n            best_found: self.best_found,\n        }\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        FindReducer {\n            match_position: self.match_position,\n        }\n    }\n}\n\nstruct FindFolder<'p, T, P> {\n    find_op: &'p P,\n    boundary: usize,\n    match_position: MatchPosition,\n    best_found: &'p AtomicUsize,\n    item: Option<T>,\n}\n\nimpl<'p, P: 'p + Fn(&T) -> bool, T> Folder<T> for FindFolder<'p, T, P> {\n    type Result = Option<T>;\n\n    fn consume(mut self, item: T) -> Self {\n        let found_best_in_range = match self.match_position {\n            MatchPosition::Leftmost => self.item.is_some(),\n            MatchPosition::Rightmost => false,\n        };\n\n        if !found_best_in_range && (self.find_op)(&item) {\n            // Update the best found index if ours is better.\n            let update =\n                self.best_found\n                    .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |current| {\n                        better_position(self.boundary, current, self.match_position)\n                            .then_some(self.boundary)\n                    });\n\n            // Save this item if our index was better or equal.\n            if update.is_ok() || update == Err(self.boundary) {\n                self.item = Some(item);\n            }\n        }\n        self\n    }\n\n    fn complete(self) -> Self::Result {\n        self.item\n    }\n\n    fn full(&self) -> bool {\n        let found_best_in_range = match self.match_position {\n            MatchPosition::Leftmost => self.item.is_some(),\n            MatchPosition::Rightmost => false,\n        };\n\n        found_best_in_range\n            || better_position(\n                self.best_found.load(Ordering::Relaxed),\n                self.boundary,\n                self.match_position,\n            )\n    }\n}\n\nstruct FindReducer {\n    match_position: MatchPosition,\n}\n\nimpl<T> Reducer<Option<T>> for FindReducer {\n    fn reduce(self, left: Option<T>, right: Option<T>) -> Option<T> {\n        match self.match_position {\n            MatchPosition::Leftmost => left.or(right),\n            MatchPosition::Rightmost => right.or(left),\n        }\n    }\n}\n"
  },
  {
    "path": "src/iter/find_first_last/test.rs",
    "content": "use super::*;\n\n#[test]\nfn same_range_first_consumers_return_correct_answer() {\n    let find_op = |x: &i32| x % 2 == 0;\n    let first_found = AtomicUsize::new(usize::MAX);\n    let far_right_consumer = FindConsumer::new(&find_op, MatchPosition::Leftmost, &first_found);\n\n    // We save a consumer that will be far to the right of the main consumer (and therefore not\n    // sharing an index range with that consumer) for fullness testing\n    let consumer = far_right_consumer.split_off_left();\n\n    // split until we have an indivisible range\n    for _ in 0..usize::BITS {\n        consumer.split_off_left();\n    }\n\n    let reducer = consumer.to_reducer();\n    // the left and right folders should now have the same range, having\n    // exhausted the resolution of usize\n    let left_folder = consumer.split_off_left().into_folder();\n    let right_folder = consumer.into_folder();\n\n    let left_folder = left_folder.consume(0).consume(1);\n    assert_eq!(left_folder.boundary, right_folder.boundary);\n    // expect not full even though a better match has been found because the\n    // ranges are the same\n    assert!(!right_folder.full());\n    assert!(far_right_consumer.full());\n    let right_folder = right_folder.consume(2).consume(3);\n    assert_eq!(\n        reducer.reduce(left_folder.complete(), right_folder.complete()),\n        Some(0)\n    );\n}\n\n#[test]\nfn same_range_last_consumers_return_correct_answer() {\n    let find_op = |x: &i32| x % 2 == 0;\n    let last_found = AtomicUsize::new(0);\n    let consumer = FindConsumer::new(&find_op, MatchPosition::Rightmost, &last_found);\n\n    // We save a consumer that will be far to the left of the main consumer (and therefore not\n    // sharing an index range with that consumer) for fullness testing\n    let far_left_consumer = consumer.split_off_left();\n\n    // split until we have an indivisible range\n    for _ in 0..usize::BITS {\n        consumer.split_off_left();\n    }\n\n    let reducer = consumer.to_reducer();\n    // due to the exact calculation in split_off_left, the very last consumer has a\n    // range of width 2, so we use the second-to-last consumer instead to get\n    // the same boundary on both folders\n    let consumer = consumer.split_off_left();\n    let left_folder = consumer.split_off_left().into_folder();\n    let right_folder = consumer.into_folder();\n    let right_folder = right_folder.consume(2).consume(3);\n    assert_eq!(left_folder.boundary, right_folder.boundary);\n    // expect not full even though a better match has been found because the\n    // ranges are the same\n    assert!(!left_folder.full());\n    assert!(far_left_consumer.full());\n    let left_folder = left_folder.consume(0).consume(1);\n    assert_eq!(\n        reducer.reduce(left_folder.complete(), right_folder.complete()),\n        Some(2)\n    );\n}\n\n// These tests requires that a folder be assigned to an iterator with more than\n// one element. We can't necessarily determine when that will happen for a given\n// input to find_first/find_last, so we test the folder directly here instead.\n#[test]\nfn find_first_folder_does_not_clobber_first_found() {\n    let best_found = AtomicUsize::new(usize::MAX);\n    let f = FindFolder {\n        find_op: &(|&_: &i32| -> bool { true }),\n        boundary: 0,\n        match_position: MatchPosition::Leftmost,\n        best_found: &best_found,\n        item: None,\n    };\n    let f = f.consume(0_i32).consume(1_i32).consume(2_i32);\n    assert!(f.full());\n    assert_eq!(f.complete(), Some(0_i32));\n}\n\n#[test]\nfn find_last_folder_yields_last_match() {\n    let best_found = AtomicUsize::new(0);\n    let f = FindFolder {\n        find_op: &(|&_: &i32| -> bool { true }),\n        boundary: 0,\n        match_position: MatchPosition::Rightmost,\n        best_found: &best_found,\n        item: None,\n    };\n    let f = f.consume(0_i32).consume(1_i32).consume(2_i32);\n    assert_eq!(f.complete(), Some(2_i32));\n}\n"
  },
  {
    "path": "src/iter/flat_map.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\n\n/// `FlatMap` maps each element to a parallel iterator, then flattens these iterators together.\n/// This struct is created by the [`flat_map()`] method on [`ParallelIterator`]\n///\n/// [`flat_map()`]: ParallelIterator::flat_map()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Clone)]\npub struct FlatMap<I, F> {\n    base: I,\n    map_op: F,\n}\n\nimpl<I: Debug, F> Debug for FlatMap<I, F> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"FlatMap\").field(\"base\", &self.base).finish()\n    }\n}\n\nimpl<I, F> FlatMap<I, F> {\n    /// Creates a new `FlatMap` iterator.\n    pub(super) fn new(base: I, map_op: F) -> Self {\n        FlatMap { base, map_op }\n    }\n}\n\nimpl<I, F, PI> ParallelIterator for FlatMap<I, F>\nwhere\n    I: ParallelIterator,\n    F: Fn(I::Item) -> PI + Sync + Send,\n    PI: IntoParallelIterator,\n{\n    type Item = PI::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer = FlatMapConsumer::new(consumer, &self.map_op);\n        self.base.drive_unindexed(consumer)\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Consumer implementation\n\nstruct FlatMapConsumer<'f, C, F> {\n    base: C,\n    map_op: &'f F,\n}\n\nimpl<'f, C, F> FlatMapConsumer<'f, C, F> {\n    fn new(base: C, map_op: &'f F) -> Self {\n        FlatMapConsumer { base, map_op }\n    }\n}\n\nimpl<'f, T, U, C, F> Consumer<T> for FlatMapConsumer<'f, C, F>\nwhere\n    C: UnindexedConsumer<U::Item>,\n    F: Fn(T) -> U + Sync,\n    U: IntoParallelIterator,\n{\n    type Folder = FlatMapFolder<'f, C, F, C::Result>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, C::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            FlatMapConsumer::new(left, self.map_op),\n            FlatMapConsumer::new(right, self.map_op),\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        FlatMapFolder {\n            base: self.base,\n            map_op: self.map_op,\n            previous: None,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\nimpl<'f, T, U, C, F> UnindexedConsumer<T> for FlatMapConsumer<'f, C, F>\nwhere\n    C: UnindexedConsumer<U::Item>,\n    F: Fn(T) -> U + Sync,\n    U: IntoParallelIterator,\n{\n    fn split_off_left(&self) -> Self {\n        FlatMapConsumer::new(self.base.split_off_left(), self.map_op)\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n\nstruct FlatMapFolder<'f, C, F, R> {\n    base: C,\n    map_op: &'f F,\n    previous: Option<R>,\n}\n\nimpl<'f, T, U, C, F> Folder<T> for FlatMapFolder<'f, C, F, C::Result>\nwhere\n    C: UnindexedConsumer<U::Item>,\n    F: Fn(T) -> U + Sync,\n    U: IntoParallelIterator,\n{\n    type Result = C::Result;\n\n    fn consume(self, item: T) -> Self {\n        let map_op = self.map_op;\n        let par_iter = map_op(item).into_par_iter();\n        let consumer = self.base.split_off_left();\n        let result = par_iter.drive_unindexed(consumer);\n\n        let previous = match self.previous {\n            None => Some(result),\n            Some(previous) => {\n                let reducer = self.base.to_reducer();\n                Some(reducer.reduce(previous, result))\n            }\n        };\n\n        FlatMapFolder {\n            base: self.base,\n            map_op,\n            previous,\n        }\n    }\n\n    fn complete(self) -> Self::Result {\n        match self.previous {\n            Some(previous) => previous,\n            None => self.base.into_folder().complete(),\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n"
  },
  {
    "path": "src/iter/flat_map_iter.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\n\n/// `FlatMapIter` maps each element to a serial iterator, then flattens these iterators together.\n/// This struct is created by the [`flat_map_iter()`] method on [`ParallelIterator`]\n///\n/// [`flat_map_iter()`]: ParallelIterator::flat_map_iter()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Clone)]\npub struct FlatMapIter<I, F> {\n    base: I,\n    map_op: F,\n}\n\nimpl<I: Debug, F> Debug for FlatMapIter<I, F> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"FlatMapIter\")\n            .field(\"base\", &self.base)\n            .finish()\n    }\n}\n\nimpl<I, F> FlatMapIter<I, F> {\n    /// Creates a new `FlatMapIter` iterator.\n    pub(super) fn new(base: I, map_op: F) -> Self {\n        FlatMapIter { base, map_op }\n    }\n}\n\nimpl<I, F, SI> ParallelIterator for FlatMapIter<I, F>\nwhere\n    I: ParallelIterator,\n    F: Fn(I::Item) -> SI + Sync + Send,\n    SI: IntoIterator<Item: Send>,\n{\n    type Item = SI::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer = FlatMapIterConsumer::new(consumer, &self.map_op);\n        self.base.drive_unindexed(consumer)\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Consumer implementation\n\nstruct FlatMapIterConsumer<'f, C, F> {\n    base: C,\n    map_op: &'f F,\n}\n\nimpl<'f, C, F> FlatMapIterConsumer<'f, C, F> {\n    fn new(base: C, map_op: &'f F) -> Self {\n        FlatMapIterConsumer { base, map_op }\n    }\n}\n\nimpl<'f, T, U, C, F> Consumer<T> for FlatMapIterConsumer<'f, C, F>\nwhere\n    C: UnindexedConsumer<U::Item>,\n    F: Fn(T) -> U + Sync,\n    U: IntoIterator,\n{\n    type Folder = FlatMapIterFolder<'f, C::Folder, F>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, C::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            FlatMapIterConsumer::new(left, self.map_op),\n            FlatMapIterConsumer::new(right, self.map_op),\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        FlatMapIterFolder {\n            base: self.base.into_folder(),\n            map_op: self.map_op,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\nimpl<'f, T, U, C, F> UnindexedConsumer<T> for FlatMapIterConsumer<'f, C, F>\nwhere\n    C: UnindexedConsumer<U::Item>,\n    F: Fn(T) -> U + Sync,\n    U: IntoIterator,\n{\n    fn split_off_left(&self) -> Self {\n        FlatMapIterConsumer::new(self.base.split_off_left(), self.map_op)\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n\nstruct FlatMapIterFolder<'f, C, F> {\n    base: C,\n    map_op: &'f F,\n}\n\nimpl<'f, T, U, C, F> Folder<T> for FlatMapIterFolder<'f, C, F>\nwhere\n    C: Folder<U::Item>,\n    F: Fn(T) -> U,\n    U: IntoIterator,\n{\n    type Result = C::Result;\n\n    fn consume(self, item: T) -> Self {\n        let map_op = self.map_op;\n        let base = self.base.consume_iter(map_op(item));\n        FlatMapIterFolder { base, map_op }\n    }\n\n    fn consume_iter<I>(self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = T>,\n    {\n        let map_op = self.map_op;\n        let iter = iter.into_iter().flat_map(map_op);\n        let base = self.base.consume_iter(iter);\n        FlatMapIterFolder { base, map_op }\n    }\n\n    fn complete(self) -> Self::Result {\n        self.base.complete()\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n"
  },
  {
    "path": "src/iter/flatten.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\n/// `Flatten` turns each element to a parallel iterator, then flattens these iterators\n/// together. This struct is created by the [`flatten()`] method on [`ParallelIterator`].\n///\n/// [`flatten()`]: ParallelIterator::flatten()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\npub struct Flatten<I> {\n    base: I,\n}\n\nimpl<I> Flatten<I> {\n    /// Creates a new `Flatten` iterator.\n    pub(super) fn new(base: I) -> Self {\n        Flatten { base }\n    }\n}\n\nimpl<I> ParallelIterator for Flatten<I>\nwhere\n    I: ParallelIterator<Item: IntoParallelIterator>,\n{\n    type Item = <I::Item as IntoParallelIterator>::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer = FlattenConsumer::new(consumer);\n        self.base.drive_unindexed(consumer)\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Consumer implementation\n\nstruct FlattenConsumer<C> {\n    base: C,\n}\n\nimpl<C> FlattenConsumer<C> {\n    fn new(base: C) -> Self {\n        FlattenConsumer { base }\n    }\n}\n\nimpl<T, C> Consumer<T> for FlattenConsumer<C>\nwhere\n    C: UnindexedConsumer<T::Item>,\n    T: IntoParallelIterator,\n{\n    type Folder = FlattenFolder<C, C::Result>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, C::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            FlattenConsumer::new(left),\n            FlattenConsumer::new(right),\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        FlattenFolder {\n            base: self.base,\n            previous: None,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\nimpl<T, C> UnindexedConsumer<T> for FlattenConsumer<C>\nwhere\n    C: UnindexedConsumer<T::Item>,\n    T: IntoParallelIterator,\n{\n    fn split_off_left(&self) -> Self {\n        FlattenConsumer::new(self.base.split_off_left())\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n\nstruct FlattenFolder<C, R> {\n    base: C,\n    previous: Option<R>,\n}\n\nimpl<T, C> Folder<T> for FlattenFolder<C, C::Result>\nwhere\n    C: UnindexedConsumer<T::Item>,\n    T: IntoParallelIterator,\n{\n    type Result = C::Result;\n\n    fn consume(self, item: T) -> Self {\n        let par_iter = item.into_par_iter();\n        let consumer = self.base.split_off_left();\n        let result = par_iter.drive_unindexed(consumer);\n\n        let previous = match self.previous {\n            None => Some(result),\n            Some(previous) => {\n                let reducer = self.base.to_reducer();\n                Some(reducer.reduce(previous, result))\n            }\n        };\n\n        FlattenFolder {\n            base: self.base,\n            previous,\n        }\n    }\n\n    fn complete(self) -> Self::Result {\n        match self.previous {\n            Some(previous) => previous,\n            None => self.base.into_folder().complete(),\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n"
  },
  {
    "path": "src/iter/flatten_iter.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\n/// `FlattenIter` turns each element to a serial iterator, then flattens these iterators\n/// together. This struct is created by the [`flatten_iter()`] method on [`ParallelIterator`].\n///\n/// [`flatten_iter()`]: ParallelIterator::flatten_iter()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\npub struct FlattenIter<I> {\n    base: I,\n}\n\nimpl<I> FlattenIter<I> {\n    /// Creates a new `FlattenIter` iterator.\n    pub(super) fn new(base: I) -> Self {\n        FlattenIter { base }\n    }\n}\n\nimpl<I> ParallelIterator for FlattenIter<I>\nwhere\n    I: ParallelIterator<Item: IntoIterator<Item: Send>>,\n{\n    type Item = <I::Item as IntoIterator>::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer = FlattenIterConsumer::new(consumer);\n        self.base.drive_unindexed(consumer)\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Consumer implementation\n\nstruct FlattenIterConsumer<C> {\n    base: C,\n}\n\nimpl<C> FlattenIterConsumer<C> {\n    fn new(base: C) -> Self {\n        FlattenIterConsumer { base }\n    }\n}\n\nimpl<T, C> Consumer<T> for FlattenIterConsumer<C>\nwhere\n    C: UnindexedConsumer<T::Item>,\n    T: IntoIterator,\n{\n    type Folder = FlattenIterFolder<C::Folder>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, C::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            FlattenIterConsumer::new(left),\n            FlattenIterConsumer::new(right),\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        FlattenIterFolder {\n            base: self.base.into_folder(),\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\nimpl<T, C> UnindexedConsumer<T> for FlattenIterConsumer<C>\nwhere\n    C: UnindexedConsumer<T::Item>,\n    T: IntoIterator,\n{\n    fn split_off_left(&self) -> Self {\n        FlattenIterConsumer::new(self.base.split_off_left())\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n\nstruct FlattenIterFolder<C> {\n    base: C,\n}\n\nimpl<T, C> Folder<T> for FlattenIterFolder<C>\nwhere\n    C: Folder<T::Item>,\n    T: IntoIterator,\n{\n    type Result = C::Result;\n\n    fn consume(self, item: T) -> Self {\n        let base = self.base.consume_iter(item);\n        FlattenIterFolder { base }\n    }\n\n    fn consume_iter<I>(self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = T>,\n    {\n        let iter = iter.into_iter().flatten();\n        let base = self.base.consume_iter(iter);\n        FlattenIterFolder { base }\n    }\n\n    fn complete(self) -> Self::Result {\n        self.base.complete()\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n"
  },
  {
    "path": "src/iter/fold.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\n\nimpl<I, ID, F> Fold<I, ID, F> {\n    pub(super) fn new(base: I, identity: ID, fold_op: F) -> Self {\n        Fold {\n            base,\n            identity,\n            fold_op,\n        }\n    }\n}\n\n/// `Fold` is an iterator that applies a function over an iterator producing a single value.\n/// This struct is created by the [`fold()`] method on [`ParallelIterator`]\n///\n/// [`fold()`]: ParallelIterator::fold()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Clone)]\npub struct Fold<I, ID, F> {\n    base: I,\n    identity: ID,\n    fold_op: F,\n}\n\nimpl<I: Debug, ID, F> Debug for Fold<I, ID, F> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"Fold\").field(\"base\", &self.base).finish()\n    }\n}\n\nimpl<U, I, ID, F> ParallelIterator for Fold<I, ID, F>\nwhere\n    I: ParallelIterator,\n    F: Fn(U, I::Item) -> U + Sync + Send,\n    ID: Fn() -> U + Sync + Send,\n    U: Send,\n{\n    type Item = U;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer1 = FoldConsumer {\n            base: consumer,\n            fold_op: &self.fold_op,\n            identity: &self.identity,\n        };\n        self.base.drive_unindexed(consumer1)\n    }\n}\n\nstruct FoldConsumer<'c, C, ID, F> {\n    base: C,\n    fold_op: &'c F,\n    identity: &'c ID,\n}\n\nimpl<'r, U, T, C, ID, F> Consumer<T> for FoldConsumer<'r, C, ID, F>\nwhere\n    C: Consumer<U>,\n    F: Fn(U, T) -> U + Sync,\n    ID: Fn() -> U + Sync,\n    U: Send,\n{\n    type Folder = FoldFolder<'r, C::Folder, U, F>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            FoldConsumer { base: left, ..self },\n            FoldConsumer {\n                base: right,\n                ..self\n            },\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        FoldFolder {\n            base: self.base.into_folder(),\n            item: (self.identity)(),\n            fold_op: self.fold_op,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\nimpl<'r, U, T, C, ID, F> UnindexedConsumer<T> for FoldConsumer<'r, C, ID, F>\nwhere\n    C: UnindexedConsumer<U>,\n    F: Fn(U, T) -> U + Sync,\n    ID: Fn() -> U + Sync,\n    U: Send,\n{\n    fn split_off_left(&self) -> Self {\n        FoldConsumer {\n            base: self.base.split_off_left(),\n            ..*self\n        }\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n\nstruct FoldFolder<'r, C, ID, F> {\n    base: C,\n    fold_op: &'r F,\n    item: ID,\n}\n\nimpl<'r, C, ID, F, T> Folder<T> for FoldFolder<'r, C, ID, F>\nwhere\n    C: Folder<ID>,\n    F: Fn(ID, T) -> ID + Sync,\n{\n    type Result = C::Result;\n\n    fn consume(self, item: T) -> Self {\n        let item = (self.fold_op)(self.item, item);\n        FoldFolder {\n            base: self.base,\n            fold_op: self.fold_op,\n            item,\n        }\n    }\n\n    fn consume_iter<I>(self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = T>,\n    {\n        fn not_full<C, ID, T>(base: &C) -> impl Fn(&T) -> bool + '_\n        where\n            C: Folder<ID>,\n        {\n            move |_| !base.full()\n        }\n\n        let base = self.base;\n        let item = iter\n            .into_iter()\n            // stop iterating if another thread has finished\n            .take_while(not_full(&base))\n            .fold(self.item, self.fold_op);\n\n        FoldFolder {\n            base,\n            item,\n            fold_op: self.fold_op,\n        }\n    }\n\n    fn complete(self) -> C::Result {\n        self.base.consume(self.item).complete()\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\n// ///////////////////////////////////////////////////////////////////////////\n\nimpl<I, U, F> FoldWith<I, U, F> {\n    pub(super) fn new(base: I, item: U, fold_op: F) -> Self {\n        FoldWith {\n            base,\n            item,\n            fold_op,\n        }\n    }\n}\n\n/// `FoldWith` is an iterator that applies a function over an iterator producing a single value.\n/// This struct is created by the [`fold_with()`] method on [`ParallelIterator`]\n///\n/// [`fold_with()`]: ParallelIterator::fold_with()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Clone)]\npub struct FoldWith<I, U, F> {\n    base: I,\n    item: U,\n    fold_op: F,\n}\n\nimpl<I: Debug, U: Debug, F> Debug for FoldWith<I, U, F> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"FoldWith\")\n            .field(\"base\", &self.base)\n            .field(\"item\", &self.item)\n            .finish()\n    }\n}\n\nimpl<U, I, F> ParallelIterator for FoldWith<I, U, F>\nwhere\n    I: ParallelIterator,\n    F: Fn(U, I::Item) -> U + Sync + Send,\n    U: Send + Clone,\n{\n    type Item = U;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer1 = FoldWithConsumer {\n            base: consumer,\n            item: self.item,\n            fold_op: &self.fold_op,\n        };\n        self.base.drive_unindexed(consumer1)\n    }\n}\n\nstruct FoldWithConsumer<'c, C, U, F> {\n    base: C,\n    item: U,\n    fold_op: &'c F,\n}\n\nimpl<'r, U, T, C, F> Consumer<T> for FoldWithConsumer<'r, C, U, F>\nwhere\n    C: Consumer<U>,\n    F: Fn(U, T) -> U + Sync,\n    U: Send + Clone,\n{\n    type Folder = FoldFolder<'r, C::Folder, U, F>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            FoldWithConsumer {\n                base: left,\n                item: self.item.clone(),\n                ..self\n            },\n            FoldWithConsumer {\n                base: right,\n                ..self\n            },\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        FoldFolder {\n            base: self.base.into_folder(),\n            item: self.item,\n            fold_op: self.fold_op,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\nimpl<'r, U, T, C, F> UnindexedConsumer<T> for FoldWithConsumer<'r, C, U, F>\nwhere\n    C: UnindexedConsumer<U>,\n    F: Fn(U, T) -> U + Sync,\n    U: Send + Clone,\n{\n    fn split_off_left(&self) -> Self {\n        FoldWithConsumer {\n            base: self.base.split_off_left(),\n            item: self.item.clone(),\n            ..*self\n        }\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n"
  },
  {
    "path": "src/iter/fold_chunks.rs",
    "content": "use std::fmt::{self, Debug};\n\nuse super::chunks::ChunkProducer;\nuse super::plumbing::*;\nuse super::*;\n\n/// `FoldChunks` is an iterator that groups elements of an underlying iterator and applies a\n/// function over them, producing a single value for each group.\n///\n/// This struct is created by the [`fold_chunks()`] method on [`IndexedParallelIterator`]\n///\n/// [`fold_chunks()`]: IndexedParallelIterator::fold_chunks()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Clone)]\npub struct FoldChunks<I, ID, F> {\n    base: I,\n    chunk_size: usize,\n    fold_op: F,\n    identity: ID,\n}\n\nimpl<I: Debug, ID, F> Debug for FoldChunks<I, ID, F> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"Fold\")\n            .field(\"base\", &self.base)\n            .field(\"chunk_size\", &self.chunk_size)\n            .finish()\n    }\n}\n\nimpl<I, ID, F> FoldChunks<I, ID, F> {\n    /// Creates a new `FoldChunks` iterator\n    pub(super) fn new(base: I, chunk_size: usize, identity: ID, fold_op: F) -> Self {\n        FoldChunks {\n            base,\n            chunk_size,\n            identity,\n            fold_op,\n        }\n    }\n}\n\nimpl<I, ID, U, F> ParallelIterator for FoldChunks<I, ID, F>\nwhere\n    I: IndexedParallelIterator,\n    ID: Fn() -> U + Send + Sync,\n    F: Fn(U, I::Item) -> U + Send + Sync,\n    U: Send,\n{\n    type Item = U;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<U>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<I, ID, U, F> IndexedParallelIterator for FoldChunks<I, ID, F>\nwhere\n    I: IndexedParallelIterator,\n    ID: Fn() -> U + Send + Sync,\n    F: Fn(U, I::Item) -> U + Send + Sync,\n    U: Send,\n{\n    fn len(&self) -> usize {\n        self.base.len().div_ceil(self.chunk_size)\n    }\n\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        let len = self.base.len();\n        return self.base.with_producer(Callback {\n            chunk_size: self.chunk_size,\n            len,\n            identity: self.identity,\n            fold_op: self.fold_op,\n            callback,\n        });\n\n        struct Callback<CB, ID, F> {\n            chunk_size: usize,\n            len: usize,\n            identity: ID,\n            fold_op: F,\n            callback: CB,\n        }\n\n        impl<T, CB, ID, U, F> ProducerCallback<T> for Callback<CB, ID, F>\n        where\n            CB: ProducerCallback<U>,\n            ID: Fn() -> U + Send + Sync,\n            F: Fn(U, T) -> U + Send + Sync,\n        {\n            type Output = CB::Output;\n\n            fn callback<P>(self, base: P) -> CB::Output\n            where\n                P: Producer<Item = T>,\n            {\n                let identity = &self.identity;\n                let fold_op = &self.fold_op;\n                let fold_iter = move |iter: P::IntoIter| iter.fold(identity(), fold_op);\n                let producer = ChunkProducer::new(self.chunk_size, self.len, base, fold_iter);\n                self.callback.callback(producer)\n            }\n        }\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use super::*;\n    use std::ops::Add;\n\n    #[test]\n    fn check_fold_chunks() {\n        let words = \"bishbashbosh!\"\n            .chars()\n            .collect::<Vec<_>>()\n            .into_par_iter()\n            .fold_chunks(4, String::new, |mut s, c| {\n                s.push(c);\n                s\n            })\n            .collect::<Vec<_>>();\n\n        assert_eq!(words, vec![\"bish\", \"bash\", \"bosh\", \"!\"]);\n    }\n\n    // 'closure' values for tests below\n    fn id() -> i32 {\n        0\n    }\n    fn sum<T, U>(x: T, y: U) -> T\n    where\n        T: Add<U, Output = T>,\n    {\n        x + y\n    }\n\n    #[test]\n    #[should_panic(expected = \"chunk_size must not be zero\")]\n    fn check_fold_chunks_zero_size() {\n        let _: Vec<i32> = vec![1, 2, 3]\n            .into_par_iter()\n            .fold_chunks(0, id, sum)\n            .collect();\n    }\n\n    #[test]\n    fn check_fold_chunks_even_size() {\n        assert_eq!(\n            vec![1 + 2 + 3, 4 + 5 + 6, 7 + 8 + 9],\n            (1..10)\n                .into_par_iter()\n                .fold_chunks(3, id, sum)\n                .collect::<Vec<i32>>()\n        );\n    }\n\n    #[test]\n    fn check_fold_chunks_empty() {\n        let v: Vec<i32> = vec![];\n        let expected: Vec<i32> = vec![];\n        assert_eq!(\n            expected,\n            v.into_par_iter()\n                .fold_chunks(2, id, sum)\n                .collect::<Vec<i32>>()\n        );\n    }\n\n    #[test]\n    fn check_fold_chunks_len() {\n        assert_eq!(4, (0..8).into_par_iter().fold_chunks(2, id, sum).len());\n        assert_eq!(3, (0..9).into_par_iter().fold_chunks(3, id, sum).len());\n        assert_eq!(3, (0..8).into_par_iter().fold_chunks(3, id, sum).len());\n        assert_eq!(1, [1].par_iter().fold_chunks(3, id, sum).len());\n        assert_eq!(0, (0..0).into_par_iter().fold_chunks(3, id, sum).len());\n    }\n\n    #[test]\n    fn check_fold_chunks_uneven() {\n        let cases: Vec<(Vec<u32>, usize, Vec<u32>)> = vec![\n            ((0..5).collect(), 3, vec![1 + 2, 3 + 4]),\n            (vec![1], 5, vec![1]),\n            ((0..4).collect(), 3, vec![1 + 2, 3]),\n        ];\n\n        for (i, (v, n, expected)) in cases.into_iter().enumerate() {\n            let mut res: Vec<u32> = vec![];\n            v.par_iter()\n                .fold_chunks(n, || 0, sum)\n                .collect_into_vec(&mut res);\n            assert_eq!(expected, res, \"Case {i} failed\");\n\n            res.truncate(0);\n            v.into_par_iter()\n                .fold_chunks(n, || 0, sum)\n                .rev()\n                .collect_into_vec(&mut res);\n            assert_eq!(\n                expected.into_iter().rev().collect::<Vec<u32>>(),\n                res,\n                \"Case {i} reversed failed\"\n            );\n        }\n    }\n}\n"
  },
  {
    "path": "src/iter/fold_chunks_with.rs",
    "content": "use std::fmt::{self, Debug};\n\nuse super::chunks::ChunkProducer;\nuse super::plumbing::*;\nuse super::*;\n\n/// `FoldChunksWith` is an iterator that groups elements of an underlying iterator and applies a\n/// function over them, producing a single value for each group.\n///\n/// This struct is created by the [`fold_chunks_with()`] method on [`IndexedParallelIterator`]\n///\n/// [`fold_chunks_with()`]: IndexedParallelIterator::fold_chunks()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Clone)]\npub struct FoldChunksWith<I, U, F> {\n    base: I,\n    chunk_size: usize,\n    item: U,\n    fold_op: F,\n}\n\nimpl<I: Debug, U: Debug, F> Debug for FoldChunksWith<I, U, F> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"Fold\")\n            .field(\"base\", &self.base)\n            .field(\"chunk_size\", &self.chunk_size)\n            .field(\"item\", &self.item)\n            .finish()\n    }\n}\n\nimpl<I, U, F> FoldChunksWith<I, U, F> {\n    /// Creates a new `FoldChunksWith` iterator\n    pub(super) fn new(base: I, chunk_size: usize, item: U, fold_op: F) -> Self {\n        FoldChunksWith {\n            base,\n            chunk_size,\n            item,\n            fold_op,\n        }\n    }\n}\n\nimpl<I, U, F> ParallelIterator for FoldChunksWith<I, U, F>\nwhere\n    I: IndexedParallelIterator,\n    U: Send + Clone,\n    F: Fn(U, I::Item) -> U + Send + Sync,\n{\n    type Item = U;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<U>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<I, U, F> IndexedParallelIterator for FoldChunksWith<I, U, F>\nwhere\n    I: IndexedParallelIterator,\n    U: Send + Clone,\n    F: Fn(U, I::Item) -> U + Send + Sync,\n{\n    fn len(&self) -> usize {\n        self.base.len().div_ceil(self.chunk_size)\n    }\n\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        let len = self.base.len();\n        return self.base.with_producer(Callback {\n            chunk_size: self.chunk_size,\n            len,\n            item: self.item,\n            fold_op: self.fold_op,\n            callback,\n        });\n\n        struct Callback<CB, T, F> {\n            chunk_size: usize,\n            len: usize,\n            item: T,\n            fold_op: F,\n            callback: CB,\n        }\n\n        impl<T, U, F, CB> ProducerCallback<T> for Callback<CB, U, F>\n        where\n            CB: ProducerCallback<U>,\n            U: Send + Clone,\n            F: Fn(U, T) -> U + Send + Sync,\n        {\n            type Output = CB::Output;\n\n            fn callback<P>(self, base: P) -> CB::Output\n            where\n                P: Producer<Item = T>,\n            {\n                let item = self.item;\n                let fold_op = &self.fold_op;\n                let fold_iter = move |iter: P::IntoIter| iter.fold(item.clone(), fold_op);\n                let producer = ChunkProducer::new(self.chunk_size, self.len, base, fold_iter);\n                self.callback.callback(producer)\n            }\n        }\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use super::*;\n    use std::ops::Add;\n\n    #[test]\n    fn check_fold_chunks_with() {\n        let words = \"bishbashbosh!\"\n            .chars()\n            .collect::<Vec<_>>()\n            .into_par_iter()\n            .fold_chunks_with(4, String::new(), |mut s, c| {\n                s.push(c);\n                s\n            })\n            .collect::<Vec<_>>();\n\n        assert_eq!(words, vec![\"bish\", \"bash\", \"bosh\", \"!\"]);\n    }\n\n    // 'closure' value for tests below\n    fn sum<T, U>(x: T, y: U) -> T\n    where\n        T: Add<U, Output = T>,\n    {\n        x + y\n    }\n\n    #[test]\n    #[should_panic(expected = \"chunk_size must not be zero\")]\n    fn check_fold_chunks_zero_size() {\n        let _: Vec<i32> = vec![1, 2, 3]\n            .into_par_iter()\n            .fold_chunks_with(0, 0, sum)\n            .collect();\n    }\n\n    #[test]\n    fn check_fold_chunks_even_size() {\n        assert_eq!(\n            vec![1 + 2 + 3, 4 + 5 + 6, 7 + 8 + 9],\n            (1..10)\n                .into_par_iter()\n                .fold_chunks_with(3, 0, sum)\n                .collect::<Vec<i32>>()\n        );\n    }\n\n    #[test]\n    fn check_fold_chunks_with_empty() {\n        let v: Vec<i32> = vec![];\n        let expected: Vec<i32> = vec![];\n        assert_eq!(\n            expected,\n            v.into_par_iter()\n                .fold_chunks_with(2, 0, sum)\n                .collect::<Vec<i32>>()\n        );\n    }\n\n    #[test]\n    fn check_fold_chunks_len() {\n        assert_eq!(4, (0..8).into_par_iter().fold_chunks_with(2, 0, sum).len());\n        assert_eq!(3, (0..9).into_par_iter().fold_chunks_with(3, 0, sum).len());\n        assert_eq!(3, (0..8).into_par_iter().fold_chunks_with(3, 0, sum).len());\n        assert_eq!(1, [1].par_iter().fold_chunks_with(3, 0, sum).len());\n        assert_eq!(0, (0..0).into_par_iter().fold_chunks_with(3, 0, sum).len());\n    }\n\n    #[test]\n    fn check_fold_chunks_uneven() {\n        let cases: Vec<(Vec<u32>, usize, Vec<u32>)> = vec![\n            ((0..5).collect(), 3, vec![1 + 2, 3 + 4]),\n            (vec![1], 5, vec![1]),\n            ((0..4).collect(), 3, vec![1 + 2, 3]),\n        ];\n\n        for (i, (v, n, expected)) in cases.into_iter().enumerate() {\n            let mut res: Vec<u32> = vec![];\n            v.par_iter()\n                .fold_chunks_with(n, 0, sum)\n                .collect_into_vec(&mut res);\n            assert_eq!(expected, res, \"Case {i} failed\");\n\n            res.truncate(0);\n            v.into_par_iter()\n                .fold_chunks_with(n, 0, sum)\n                .rev()\n                .collect_into_vec(&mut res);\n            assert_eq!(\n                expected.into_iter().rev().collect::<Vec<u32>>(),\n                res,\n                \"Case {i} reversed failed\"\n            );\n        }\n    }\n}\n"
  },
  {
    "path": "src/iter/for_each.rs",
    "content": "use super::noop::*;\nuse super::plumbing::*;\nuse super::ParallelIterator;\n\npub(super) fn for_each<I, F, T>(pi: I, op: &F)\nwhere\n    I: ParallelIterator<Item = T>,\n    F: Fn(T) + Sync,\n    T: Send,\n{\n    let consumer = ForEachConsumer { op };\n    pi.drive_unindexed(consumer)\n}\n\nstruct ForEachConsumer<'f, F> {\n    op: &'f F,\n}\n\nimpl<'f, F, T> Consumer<T> for ForEachConsumer<'f, F>\nwhere\n    F: Fn(T) + Sync,\n{\n    type Folder = ForEachConsumer<'f, F>;\n    type Reducer = NoopReducer;\n    type Result = ();\n\n    fn split_at(self, _index: usize) -> (Self, Self, NoopReducer) {\n        (self.split_off_left(), self, NoopReducer)\n    }\n\n    fn into_folder(self) -> Self {\n        self\n    }\n\n    fn full(&self) -> bool {\n        false\n    }\n}\n\nimpl<'f, F, T> Folder<T> for ForEachConsumer<'f, F>\nwhere\n    F: Fn(T) + Sync,\n{\n    type Result = ();\n\n    fn consume(self, item: T) -> Self {\n        (self.op)(item);\n        self\n    }\n\n    fn consume_iter<I>(self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = T>,\n    {\n        iter.into_iter().for_each(self.op);\n        self\n    }\n\n    fn complete(self) {}\n\n    fn full(&self) -> bool {\n        false\n    }\n}\n\nimpl<'f, F, T> UnindexedConsumer<T> for ForEachConsumer<'f, F>\nwhere\n    F: Fn(T) + Sync,\n{\n    fn split_off_left(&self) -> Self {\n        ForEachConsumer { op: self.op }\n    }\n\n    fn to_reducer(&self) -> NoopReducer {\n        NoopReducer\n    }\n}\n"
  },
  {
    "path": "src/iter/from_par_iter.rs",
    "content": "use super::noop::NoopConsumer;\nuse super::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator};\n\nuse std::borrow::Cow;\nuse std::collections::LinkedList;\nuse std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};\nuse std::collections::{BinaryHeap, VecDeque};\nuse std::ffi::{OsStr, OsString};\nuse std::hash::{BuildHasher, Hash};\nuse std::rc::Rc;\nuse std::sync::Arc;\n\n/// Creates an empty default collection and extends it.\nfn collect_extended<C, I>(par_iter: I) -> C\nwhere\n    I: IntoParallelIterator,\n    C: ParallelExtend<I::Item> + Default,\n{\n    let mut collection = C::default();\n    collection.par_extend(par_iter);\n    collection\n}\n\n/// Collects items from a parallel iterator into a vector.\nimpl<T> FromParallelIterator<T> for Vec<T>\nwhere\n    T: Send,\n{\n    fn from_par_iter<I>(par_iter: I) -> Self\n    where\n        I: IntoParallelIterator<Item = T>,\n    {\n        collect_extended(par_iter)\n    }\n}\n\n/// Collects items from a parallel iterator into a boxed slice.\nimpl<T> FromParallelIterator<T> for Box<[T]>\nwhere\n    T: Send,\n{\n    fn from_par_iter<I>(par_iter: I) -> Self\n    where\n        I: IntoParallelIterator<Item = T>,\n    {\n        Vec::from_par_iter(par_iter).into()\n    }\n}\n\n/// Collects items from a parallel iterator into a reference-counted slice.\nimpl<T> FromParallelIterator<T> for Rc<[T]>\nwhere\n    T: Send,\n{\n    fn from_par_iter<I>(par_iter: I) -> Self\n    where\n        I: IntoParallelIterator<Item = T>,\n    {\n        Vec::from_par_iter(par_iter).into()\n    }\n}\n\n/// Collects items from a parallel iterator into an atomically-reference-counted slice.\nimpl<T> FromParallelIterator<T> for Arc<[T]>\nwhere\n    T: Send,\n{\n    fn from_par_iter<I>(par_iter: I) -> Self\n    where\n        I: IntoParallelIterator<Item = T>,\n    {\n        Vec::from_par_iter(par_iter).into()\n    }\n}\n\n/// Collects items from a parallel iterator into a vecdeque.\nimpl<T> FromParallelIterator<T> for VecDeque<T>\nwhere\n    T: Send,\n{\n    fn from_par_iter<I>(par_iter: I) -> Self\n    where\n        I: IntoParallelIterator<Item = T>,\n    {\n        Vec::from_par_iter(par_iter).into()\n    }\n}\n\n/// Collects items from a parallel iterator into a binaryheap.\n/// The heap-ordering is calculated serially after all items are collected.\nimpl<T> FromParallelIterator<T> for BinaryHeap<T>\nwhere\n    T: Ord + Send,\n{\n    fn from_par_iter<I>(par_iter: I) -> Self\n    where\n        I: IntoParallelIterator<Item = T>,\n    {\n        Vec::from_par_iter(par_iter).into()\n    }\n}\n\n/// Collects items from a parallel iterator into a freshly allocated\n/// linked list.\nimpl<T> FromParallelIterator<T> for LinkedList<T>\nwhere\n    T: Send,\n{\n    fn from_par_iter<I>(par_iter: I) -> Self\n    where\n        I: IntoParallelIterator<Item = T>,\n    {\n        collect_extended(par_iter)\n    }\n}\n\n/// Collects (key, value) pairs from a parallel iterator into a\n/// hashmap. If multiple pairs correspond to the same key, then the\n/// ones produced earlier in the parallel iterator will be\n/// overwritten, just as with a sequential iterator.\nimpl<K, V, S> FromParallelIterator<(K, V)> for HashMap<K, V, S>\nwhere\n    K: Eq + Hash + Send,\n    V: Send,\n    S: BuildHasher + Default + Send,\n{\n    fn from_par_iter<I>(par_iter: I) -> Self\n    where\n        I: IntoParallelIterator<Item = (K, V)>,\n    {\n        collect_extended(par_iter)\n    }\n}\n\n/// Collects (key, value) pairs from a parallel iterator into a\n/// btreemap. If multiple pairs correspond to the same key, then the\n/// ones produced earlier in the parallel iterator will be\n/// overwritten, just as with a sequential iterator.\nimpl<K, V> FromParallelIterator<(K, V)> for BTreeMap<K, V>\nwhere\n    K: Ord + Send,\n    V: Send,\n{\n    fn from_par_iter<I>(par_iter: I) -> Self\n    where\n        I: IntoParallelIterator<Item = (K, V)>,\n    {\n        collect_extended(par_iter)\n    }\n}\n\n/// Collects values from a parallel iterator into a hashset.\nimpl<V, S> FromParallelIterator<V> for HashSet<V, S>\nwhere\n    V: Eq + Hash + Send,\n    S: BuildHasher + Default + Send,\n{\n    fn from_par_iter<I>(par_iter: I) -> Self\n    where\n        I: IntoParallelIterator<Item = V>,\n    {\n        collect_extended(par_iter)\n    }\n}\n\n/// Collects values from a parallel iterator into a btreeset.\nimpl<V> FromParallelIterator<V> for BTreeSet<V>\nwhere\n    V: Send + Ord,\n{\n    fn from_par_iter<I>(par_iter: I) -> Self\n    where\n        I: IntoParallelIterator<Item = V>,\n    {\n        collect_extended(par_iter)\n    }\n}\n\nmacro_rules! collect_string {\n    ($desc:literal, $item:ty $(, $a:lifetime)?) => {\n        #[doc = concat!(\"Collects \", $desc, \" from a parallel iterator into a string.\")]\n        impl$(<$a>)? FromParallelIterator<$item> for String {\n            fn from_par_iter<I>(par_iter: I) -> Self\n            where\n                I: IntoParallelIterator<Item = $item>,\n            {\n                collect_extended(par_iter)\n            }\n        }\n\n        #[doc = concat!(\"Collects \", $desc, \" from a parallel iterator into a boxed string.\")]\n        impl$(<$a>)? FromParallelIterator<$item> for Box<str> {\n            fn from_par_iter<I>(par_iter: I) -> Self\n            where\n                I: IntoParallelIterator<Item = $item>,\n            {\n                String::from_par_iter(par_iter).into_boxed_str()\n            }\n        }\n    }\n}\n\ncollect_string!(\"characters\", char);\ncollect_string!(\"characters\", &'a char, 'a);\ncollect_string!(\"string slices\", &'a str, 'a);\ncollect_string!(\"string slices\", Cow<'a, str>, 'a);\ncollect_string!(\"boxed strings\", Box<str>);\ncollect_string!(\"strings\", String);\n\n/// Collects OS-string slices from a parallel iterator into an OS-string.\nimpl<'a> FromParallelIterator<&'a OsStr> for OsString {\n    fn from_par_iter<I>(par_iter: I) -> Self\n    where\n        I: IntoParallelIterator<Item = &'a OsStr>,\n    {\n        collect_extended(par_iter)\n    }\n}\n\n/// Collects OS-strings from a parallel iterator into one large OS-string.\nimpl FromParallelIterator<OsString> for OsString {\n    fn from_par_iter<I>(par_iter: I) -> Self\n    where\n        I: IntoParallelIterator<Item = OsString>,\n    {\n        collect_extended(par_iter)\n    }\n}\n\n/// Collects OS-string slices from a parallel iterator into an OS-string.\nimpl<'a> FromParallelIterator<Cow<'a, OsStr>> for OsString {\n    fn from_par_iter<I>(par_iter: I) -> Self\n    where\n        I: IntoParallelIterator<Item = Cow<'a, OsStr>>,\n    {\n        collect_extended(par_iter)\n    }\n}\n\n/// Collects an arbitrary `Cow` collection.\n///\n/// Note, the standard library only has `FromIterator` for `Cow<'a, str>` and\n/// `Cow<'a, [T]>`, because no one thought to add a blanket implementation\n/// before it was stabilized.\nimpl<'a, C, T> FromParallelIterator<T> for Cow<'a, C>\nwhere\n    C: ToOwned<Owned: FromParallelIterator<T>> + ?Sized,\n    T: Send,\n{\n    fn from_par_iter<I>(par_iter: I) -> Self\n    where\n        I: IntoParallelIterator<Item = T>,\n    {\n        Cow::Owned(C::Owned::from_par_iter(par_iter))\n    }\n}\n\n/// Collapses all unit items from a parallel iterator into one.\n///\n/// This is more useful when combined with higher-level abstractions, like\n/// collecting to a `Result<(), E>` where you only care about errors:\n///\n/// ```\n/// use std::io::*;\n/// use rayon::prelude::*;\n///\n/// let data = vec![1, 2, 3, 4, 5];\n/// let res: Result<()> = data.par_iter()\n///     .map(|x| writeln!(stdout(), \"{}\", x))\n///     .collect();\n/// assert!(res.is_ok());\n/// ```\nimpl FromParallelIterator<()> for () {\n    fn from_par_iter<I>(par_iter: I) -> Self\n    where\n        I: IntoParallelIterator<Item = ()>,\n    {\n        par_iter.into_par_iter().drive_unindexed(NoopConsumer)\n    }\n}\n"
  },
  {
    "path": "src/iter/inspect.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\nuse std::iter;\n\n/// `Inspect` is an iterator that calls a function with a reference to each\n/// element before yielding it.\n///\n/// This struct is created by the [`inspect()`] method on [`ParallelIterator`]\n///\n/// [`inspect()`]: ParallelIterator::inspect()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Clone)]\npub struct Inspect<I, F> {\n    base: I,\n    inspect_op: F,\n}\n\nimpl<I: Debug, F> Debug for Inspect<I, F> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"Inspect\").field(\"base\", &self.base).finish()\n    }\n}\n\nimpl<I, F> Inspect<I, F> {\n    /// Creates a new `Inspect` iterator.\n    pub(super) fn new(base: I, inspect_op: F) -> Self {\n        Inspect { base, inspect_op }\n    }\n}\n\nimpl<I, F> ParallelIterator for Inspect<I, F>\nwhere\n    I: ParallelIterator,\n    F: Fn(&I::Item) + Sync + Send,\n{\n    type Item = I::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer1 = InspectConsumer::new(consumer, &self.inspect_op);\n        self.base.drive_unindexed(consumer1)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        self.base.opt_len()\n    }\n}\n\nimpl<I, F> IndexedParallelIterator for Inspect<I, F>\nwhere\n    I: IndexedParallelIterator,\n    F: Fn(&I::Item) + Sync + Send,\n{\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        let consumer1 = InspectConsumer::new(consumer, &self.inspect_op);\n        self.base.drive(consumer1)\n    }\n\n    fn len(&self) -> usize {\n        self.base.len()\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        return self.base.with_producer(Callback {\n            callback,\n            inspect_op: self.inspect_op,\n        });\n\n        struct Callback<CB, F> {\n            callback: CB,\n            inspect_op: F,\n        }\n\n        impl<T, F, CB> ProducerCallback<T> for Callback<CB, F>\n        where\n            CB: ProducerCallback<T>,\n            F: Fn(&T) + Sync,\n        {\n            type Output = CB::Output;\n\n            fn callback<P>(self, base: P) -> CB::Output\n            where\n                P: Producer<Item = T>,\n            {\n                let producer = InspectProducer {\n                    base,\n                    inspect_op: &self.inspect_op,\n                };\n                self.callback.callback(producer)\n            }\n        }\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n\nstruct InspectProducer<'f, P, F> {\n    base: P,\n    inspect_op: &'f F,\n}\n\nimpl<'f, P, F> Producer for InspectProducer<'f, P, F>\nwhere\n    P: Producer,\n    F: Fn(&P::Item) + Sync,\n{\n    type Item = P::Item;\n    type IntoIter = iter::Inspect<P::IntoIter, &'f F>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.base.into_iter().inspect(self.inspect_op)\n    }\n\n    fn min_len(&self) -> usize {\n        self.base.min_len()\n    }\n\n    fn max_len(&self) -> usize {\n        self.base.max_len()\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let (left, right) = self.base.split_at(index);\n        (\n            InspectProducer {\n                base: left,\n                inspect_op: self.inspect_op,\n            },\n            InspectProducer {\n                base: right,\n                inspect_op: self.inspect_op,\n            },\n        )\n    }\n\n    fn fold_with<G>(self, folder: G) -> G\n    where\n        G: Folder<Self::Item>,\n    {\n        let folder1 = InspectFolder {\n            base: folder,\n            inspect_op: self.inspect_op,\n        };\n        self.base.fold_with(folder1).base\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Consumer implementation\n\nstruct InspectConsumer<'f, C, F> {\n    base: C,\n    inspect_op: &'f F,\n}\n\nimpl<'f, C, F> InspectConsumer<'f, C, F> {\n    fn new(base: C, inspect_op: &'f F) -> Self {\n        InspectConsumer { base, inspect_op }\n    }\n}\n\nimpl<'f, T, C, F> Consumer<T> for InspectConsumer<'f, C, F>\nwhere\n    C: Consumer<T>,\n    F: Fn(&T) + Sync,\n{\n    type Folder = InspectFolder<'f, C::Folder, F>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            InspectConsumer::new(left, self.inspect_op),\n            InspectConsumer::new(right, self.inspect_op),\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        InspectFolder {\n            base: self.base.into_folder(),\n            inspect_op: self.inspect_op,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\nimpl<'f, T, C, F> UnindexedConsumer<T> for InspectConsumer<'f, C, F>\nwhere\n    C: UnindexedConsumer<T>,\n    F: Fn(&T) + Sync,\n{\n    fn split_off_left(&self) -> Self {\n        InspectConsumer::new(self.base.split_off_left(), self.inspect_op)\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n\nstruct InspectFolder<'f, C, F> {\n    base: C,\n    inspect_op: &'f F,\n}\n\nimpl<'f, T, C, F> Folder<T> for InspectFolder<'f, C, F>\nwhere\n    C: Folder<T>,\n    F: Fn(&T),\n{\n    type Result = C::Result;\n\n    fn consume(self, item: T) -> Self {\n        (self.inspect_op)(&item);\n        InspectFolder {\n            base: self.base.consume(item),\n            inspect_op: self.inspect_op,\n        }\n    }\n\n    fn consume_iter<I>(mut self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = T>,\n    {\n        self.base = self\n            .base\n            .consume_iter(iter.into_iter().inspect(self.inspect_op));\n        self\n    }\n\n    fn complete(self) -> C::Result {\n        self.base.complete()\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n"
  },
  {
    "path": "src/iter/interleave.rs",
    "content": "use super::plumbing::*;\nuse super::*;\nuse std::iter::Fuse;\n\n/// `Interleave` is an iterator that interleaves elements of iterators\n/// `i` and `j` in one continuous iterator. This struct is created by\n/// the [`interleave()`] method on [`IndexedParallelIterator`]\n///\n/// [`interleave()`]: IndexedParallelIterator::interleave()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\npub struct Interleave<I, J> {\n    i: I,\n    j: J,\n}\n\nimpl<I, J> Interleave<I, J> {\n    /// Creates a new `Interleave` iterator\n    pub(super) fn new(i: I, j: J) -> Self {\n        Interleave { i, j }\n    }\n}\n\nimpl<I, J> ParallelIterator for Interleave<I, J>\nwhere\n    I: IndexedParallelIterator,\n    J: IndexedParallelIterator<Item = I::Item>,\n{\n    type Item = I::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<I::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<I, J> IndexedParallelIterator for Interleave<I, J>\nwhere\n    I: IndexedParallelIterator,\n    J: IndexedParallelIterator<Item = I::Item>,\n{\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.i.len().checked_add(self.j.len()).expect(\"overflow\")\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        let (i_len, j_len) = (self.i.len(), self.j.len());\n        return self.i.with_producer(CallbackI {\n            callback,\n            i_len,\n            j_len,\n            i_next: false,\n            j: self.j,\n        });\n\n        struct CallbackI<CB, J> {\n            callback: CB,\n            i_len: usize,\n            j_len: usize,\n            i_next: bool,\n            j: J,\n        }\n\n        impl<CB, J> ProducerCallback<J::Item> for CallbackI<CB, J>\n        where\n            J: IndexedParallelIterator,\n            CB: ProducerCallback<J::Item>,\n        {\n            type Output = CB::Output;\n\n            fn callback<I>(self, i_producer: I) -> Self::Output\n            where\n                I: Producer<Item = J::Item>,\n            {\n                self.j.with_producer(CallbackJ {\n                    i_producer,\n                    i_len: self.i_len,\n                    j_len: self.j_len,\n                    i_next: self.i_next,\n                    callback: self.callback,\n                })\n            }\n        }\n\n        struct CallbackJ<CB, I> {\n            callback: CB,\n            i_len: usize,\n            j_len: usize,\n            i_next: bool,\n            i_producer: I,\n        }\n\n        impl<CB, I> ProducerCallback<I::Item> for CallbackJ<CB, I>\n        where\n            I: Producer,\n            CB: ProducerCallback<I::Item>,\n        {\n            type Output = CB::Output;\n\n            fn callback<J>(self, j_producer: J) -> Self::Output\n            where\n                J: Producer<Item = I::Item>,\n            {\n                let producer = InterleaveProducer::new(\n                    self.i_producer,\n                    j_producer,\n                    self.i_len,\n                    self.j_len,\n                    self.i_next,\n                );\n                self.callback.callback(producer)\n            }\n        }\n    }\n}\n\nstruct InterleaveProducer<I, J>\nwhere\n    I: Producer,\n    J: Producer<Item = I::Item>,\n{\n    i: I,\n    j: J,\n    i_len: usize,\n    j_len: usize,\n    i_next: bool,\n}\n\nimpl<I, J> InterleaveProducer<I, J>\nwhere\n    I: Producer,\n    J: Producer<Item = I::Item>,\n{\n    fn new(i: I, j: J, i_len: usize, j_len: usize, i_next: bool) -> InterleaveProducer<I, J> {\n        InterleaveProducer {\n            i,\n            j,\n            i_len,\n            j_len,\n            i_next,\n        }\n    }\n}\n\nimpl<I, J> Producer for InterleaveProducer<I, J>\nwhere\n    I: Producer,\n    J: Producer<Item = I::Item>,\n{\n    type Item = I::Item;\n    type IntoIter = InterleaveSeq<I::IntoIter, J::IntoIter>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        InterleaveSeq {\n            i: self.i.into_iter().fuse(),\n            j: self.j.into_iter().fuse(),\n            i_next: self.i_next,\n        }\n    }\n\n    fn min_len(&self) -> usize {\n        Ord::max(self.i.min_len(), self.j.min_len())\n    }\n\n    fn max_len(&self) -> usize {\n        Ord::min(self.i.max_len(), self.j.max_len())\n    }\n\n    /// We know 0 < index <= self.i_len + self.j_len\n    ///\n    /// Find a, b satisfying:\n    ///\n    ///  (1) 0 < a <= self.i_len\n    ///  (2) 0 < b <= self.j_len\n    ///  (3) a + b == index\n    ///\n    /// For even splits, set a = b = index/2.\n    /// For odd splits, set a = (index/2)+1, b = index/2, if `i`\n    /// should yield the next element, otherwise, if `j` should yield\n    /// the next element, set a = index/2 and b = (index/2)+1\n    fn split_at(self, index: usize) -> (Self, Self) {\n        #[inline]\n        fn odd_offset(flag: bool) -> usize {\n            (!flag) as usize\n        }\n\n        let even = index % 2 == 0;\n        let idx = index >> 1;\n\n        // desired split\n        let (i_idx, j_idx) = (\n            idx + odd_offset(even || self.i_next),\n            idx + odd_offset(even || !self.i_next),\n        );\n\n        let (i_split, j_split) = if self.i_len >= i_idx && self.j_len >= j_idx {\n            (i_idx, j_idx)\n        } else if self.i_len >= i_idx {\n            // j too short\n            (index - self.j_len, self.j_len)\n        } else {\n            // i too short\n            (self.i_len, index - self.i_len)\n        };\n\n        let trailing_i_next = even == self.i_next;\n        let (i_left, i_right) = self.i.split_at(i_split);\n        let (j_left, j_right) = self.j.split_at(j_split);\n\n        (\n            InterleaveProducer::new(i_left, j_left, i_split, j_split, self.i_next),\n            InterleaveProducer::new(\n                i_right,\n                j_right,\n                self.i_len - i_split,\n                self.j_len - j_split,\n                trailing_i_next,\n            ),\n        )\n    }\n}\n\n/// Wrapper for Interleave to implement DoubleEndedIterator and\n/// ExactSizeIterator.\n///\n/// This iterator is fused.\nstruct InterleaveSeq<I, J> {\n    i: Fuse<I>,\n    j: Fuse<J>,\n\n    /// Flag to control which iterator should provide the next element. When\n    /// `false` then `i` produces the next element, otherwise `j` produces the\n    /// next element.\n    i_next: bool,\n}\n\n/// Iterator implementation for InterleaveSeq. This implementation is\n/// taken more or less verbatim from itertools. It is replicated here\n/// (instead of calling itertools directly), because we also need to\n/// implement `DoubledEndedIterator` and `ExactSizeIterator`.\nimpl<I, J> Iterator for InterleaveSeq<I, J>\nwhere\n    I: Iterator,\n    J: Iterator<Item = I::Item>,\n{\n    type Item = I::Item;\n\n    #[inline]\n    fn next(&mut self) -> Option<Self::Item> {\n        self.i_next = !self.i_next;\n        if self.i_next {\n            match self.i.next() {\n                None => self.j.next(),\n                r => r,\n            }\n        } else {\n            match self.j.next() {\n                None => self.i.next(),\n                r => r,\n            }\n        }\n    }\n\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        let (ih, jh) = (self.i.size_hint(), self.j.size_hint());\n        let min = ih.0.saturating_add(jh.0);\n        let max = match (ih.1, jh.1) {\n            (Some(x), Some(y)) => x.checked_add(y),\n            _ => None,\n        };\n        (min, max)\n    }\n}\n\n// The implementation for DoubleEndedIterator requires\n// ExactSizeIterator to provide `next_back()`. The last element will\n// come from the iterator that runs out last (ie has the most elements\n// in it). If the iterators have the same number of elements, then the\n// last iterator will provide the last element.\nimpl<I, J> DoubleEndedIterator for InterleaveSeq<I, J>\nwhere\n    I: DoubleEndedIterator + ExactSizeIterator,\n    J: DoubleEndedIterator<Item = I::Item> + ExactSizeIterator<Item = I::Item>,\n{\n    #[inline]\n    fn next_back(&mut self) -> Option<I::Item> {\n        match self.i.len().cmp(&self.j.len()) {\n            Ordering::Less => self.j.next_back(),\n            Ordering::Equal => {\n                if self.i_next {\n                    self.i.next_back()\n                } else {\n                    self.j.next_back()\n                }\n            }\n            Ordering::Greater => self.i.next_back(),\n        }\n    }\n}\n\nimpl<I, J> ExactSizeIterator for InterleaveSeq<I, J>\nwhere\n    I: ExactSizeIterator,\n    J: ExactSizeIterator<Item = I::Item>,\n{\n    #[inline]\n    fn len(&self) -> usize {\n        self.i.len() + self.j.len()\n    }\n}\n"
  },
  {
    "path": "src/iter/interleave_shortest.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\n/// `InterleaveShortest` is an iterator that works similarly to\n/// `Interleave`, but this version stops returning elements once one\n/// of the iterators run out.\n///\n/// This struct is created by the [`interleave_shortest()`] method on\n/// [`IndexedParallelIterator`].\n///\n/// [`interleave_shortest()`]: IndexedParallelIterator::interleave_shortest()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\npub struct InterleaveShortest<I, J> {\n    interleave: Interleave<Take<I>, Take<J>>,\n}\n\nimpl<I, J> InterleaveShortest<I, J>\nwhere\n    I: IndexedParallelIterator,\n    J: IndexedParallelIterator<Item = I::Item>,\n{\n    /// Creates a new `InterleaveShortest` iterator\n    pub(super) fn new(i: I, j: J) -> Self {\n        InterleaveShortest {\n            interleave: if i.len() <= j.len() {\n                // take equal lengths from both iterators\n                let n = i.len();\n                i.take(n).interleave(j.take(n))\n            } else {\n                // take one extra item from the first iterator\n                let n = j.len();\n                i.take(n + 1).interleave(j.take(n))\n            },\n        }\n    }\n}\n\nimpl<I, J> ParallelIterator for InterleaveShortest<I, J>\nwhere\n    I: IndexedParallelIterator,\n    J: IndexedParallelIterator<Item = I::Item>,\n{\n    type Item = I::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<I::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<I, J> IndexedParallelIterator for InterleaveShortest<I, J>\nwhere\n    I: IndexedParallelIterator,\n    J: IndexedParallelIterator<Item = I::Item>,\n{\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.interleave.len()\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        self.interleave.with_producer(callback)\n    }\n}\n"
  },
  {
    "path": "src/iter/intersperse.rs",
    "content": "use super::plumbing::*;\nuse super::*;\nuse std::cell::Cell;\nuse std::iter::{self, Fuse};\n\n/// `Intersperse` is an iterator that inserts a particular item between each\n/// item of the adapted iterator.  This struct is created by the\n/// [`intersperse()`] method on [`ParallelIterator`]\n///\n/// [`intersperse()`]: ParallelIterator::intersperse()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Clone, Debug)]\npub struct Intersperse<I>\nwhere\n    I: ParallelIterator,\n{\n    base: I,\n    item: I::Item,\n}\n\nimpl<I> Intersperse<I>\nwhere\n    I: ParallelIterator<Item: Clone>,\n{\n    /// Creates a new `Intersperse` iterator\n    pub(super) fn new(base: I, item: I::Item) -> Self {\n        Intersperse { base, item }\n    }\n}\n\nimpl<I> ParallelIterator for Intersperse<I>\nwhere\n    I: ParallelIterator<Item: Clone>,\n{\n    type Item = I::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<I::Item>,\n    {\n        let consumer1 = IntersperseConsumer::new(consumer, self.item);\n        self.base.drive_unindexed(consumer1)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        match self.base.opt_len()? {\n            0 => Some(0),\n            len => len.checked_add(len - 1),\n        }\n    }\n}\n\nimpl<I> IndexedParallelIterator for Intersperse<I>\nwhere\n    I: IndexedParallelIterator<Item: Clone>,\n{\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        let consumer1 = IntersperseConsumer::new(consumer, self.item);\n        self.base.drive(consumer1)\n    }\n\n    fn len(&self) -> usize {\n        let len = self.base.len();\n        if len > 0 {\n            len.checked_add(len - 1).expect(\"overflow\")\n        } else {\n            0\n        }\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        let len = self.len();\n        return self.base.with_producer(Callback {\n            callback,\n            item: self.item,\n            len,\n        });\n\n        struct Callback<CB, T> {\n            callback: CB,\n            item: T,\n            len: usize,\n        }\n\n        impl<T, CB> ProducerCallback<T> for Callback<CB, T>\n        where\n            CB: ProducerCallback<T>,\n            T: Clone + Send,\n        {\n            type Output = CB::Output;\n\n            fn callback<P>(self, base: P) -> CB::Output\n            where\n                P: Producer<Item = T>,\n            {\n                let producer = IntersperseProducer::new(base, self.item, self.len);\n                self.callback.callback(producer)\n            }\n        }\n    }\n}\n\nstruct IntersperseProducer<P>\nwhere\n    P: Producer,\n{\n    base: P,\n    item: P::Item,\n    len: usize,\n    clone_first: bool,\n}\n\nimpl<P> IntersperseProducer<P>\nwhere\n    P: Producer,\n{\n    fn new(base: P, item: P::Item, len: usize) -> Self {\n        IntersperseProducer {\n            base,\n            item,\n            len,\n            clone_first: false,\n        }\n    }\n}\n\nimpl<P> Producer for IntersperseProducer<P>\nwhere\n    P: Producer<Item: Clone + Send>,\n{\n    type Item = P::Item;\n    type IntoIter = IntersperseIter<P::IntoIter>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        IntersperseIter {\n            base: self.base.into_iter().fuse(),\n            item: self.item,\n            clone_first: self.len > 0 && self.clone_first,\n\n            // If there's more than one item, then even lengths end the opposite\n            // of how they started with respect to interspersed clones.\n            clone_last: self.len > 1 && ((self.len & 1 == 0) ^ self.clone_first),\n        }\n    }\n\n    fn min_len(&self) -> usize {\n        self.base.min_len()\n    }\n    fn max_len(&self) -> usize {\n        self.base.max_len()\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        debug_assert!(index <= self.len);\n\n        // The left needs half of the items from the base producer, and the\n        // other half will be our interspersed item.  If we're not leading with\n        // a cloned item, then we need to round up the base number of items,\n        // otherwise round down.\n        let base_index = (index + !self.clone_first as usize) / 2;\n        let (left_base, right_base) = self.base.split_at(base_index);\n\n        let left = IntersperseProducer {\n            base: left_base,\n            item: self.item.clone(),\n            len: index,\n            clone_first: self.clone_first,\n        };\n\n        let right = IntersperseProducer {\n            base: right_base,\n            item: self.item,\n            len: self.len - index,\n\n            // If the index is odd, the right side toggles `clone_first`.\n            clone_first: (index & 1 == 1) ^ self.clone_first,\n        };\n\n        (left, right)\n    }\n\n    fn fold_with<F>(self, folder: F) -> F\n    where\n        F: Folder<Self::Item>,\n    {\n        let folder1 = IntersperseFolder {\n            base: folder,\n            item: self.item,\n            clone_first: self.clone_first,\n        };\n        self.base.fold_with(folder1).base\n    }\n}\n\nstruct IntersperseIter<I>\nwhere\n    I: Iterator,\n{\n    base: Fuse<I>,\n    item: I::Item,\n    clone_first: bool,\n    clone_last: bool,\n}\n\nimpl<I> Iterator for IntersperseIter<I>\nwhere\n    I: DoubleEndedIterator<Item: Clone> + ExactSizeIterator,\n{\n    type Item = I::Item;\n\n    fn next(&mut self) -> Option<Self::Item> {\n        if self.clone_first {\n            self.clone_first = false;\n            Some(self.item.clone())\n        } else if let next @ Some(_) = self.base.next() {\n            // If there are any items left, we'll need another clone in front.\n            self.clone_first = self.base.len() != 0;\n            next\n        } else if self.clone_last {\n            self.clone_last = false;\n            Some(self.item.clone())\n        } else {\n            None\n        }\n    }\n\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        let len = self.len();\n        (len, Some(len))\n    }\n}\n\nimpl<I> DoubleEndedIterator for IntersperseIter<I>\nwhere\n    I: DoubleEndedIterator<Item: Clone> + ExactSizeIterator,\n{\n    fn next_back(&mut self) -> Option<Self::Item> {\n        if self.clone_last {\n            self.clone_last = false;\n            Some(self.item.clone())\n        } else if let next_back @ Some(_) = self.base.next_back() {\n            // If there are any items left, we'll need another clone in back.\n            self.clone_last = self.base.len() != 0;\n            next_back\n        } else if self.clone_first {\n            self.clone_first = false;\n            Some(self.item.clone())\n        } else {\n            None\n        }\n    }\n}\n\nimpl<I> ExactSizeIterator for IntersperseIter<I>\nwhere\n    I: DoubleEndedIterator<Item: Clone> + ExactSizeIterator,\n{\n    fn len(&self) -> usize {\n        let len = self.base.len();\n        len + len.saturating_sub(1) + self.clone_first as usize + self.clone_last as usize\n    }\n}\n\nstruct IntersperseConsumer<C, T> {\n    base: C,\n    item: T,\n    clone_first: Cell<bool>,\n}\n\nimpl<C, T> IntersperseConsumer<C, T>\nwhere\n    C: Consumer<T>,\n{\n    fn new(base: C, item: T) -> Self {\n        IntersperseConsumer {\n            base,\n            item,\n            clone_first: false.into(),\n        }\n    }\n}\n\nimpl<C, T> Consumer<T> for IntersperseConsumer<C, T>\nwhere\n    C: Consumer<T>,\n    T: Clone + Send,\n{\n    type Folder = IntersperseFolder<C::Folder, T>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(mut self, index: usize) -> (Self, Self, Self::Reducer) {\n        // We'll feed twice as many items to the base consumer, except if we're\n        // not currently leading with a cloned item, then it's one less.\n        let base_index = index + index.saturating_sub(!self.clone_first.get() as usize);\n        let (left, right, reducer) = self.base.split_at(base_index);\n\n        let right = IntersperseConsumer {\n            base: right,\n            item: self.item.clone(),\n            clone_first: true.into(),\n        };\n        self.base = left;\n        (self, right, reducer)\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        IntersperseFolder {\n            base: self.base.into_folder(),\n            item: self.item,\n            clone_first: self.clone_first.get(),\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\nimpl<C, T> UnindexedConsumer<T> for IntersperseConsumer<C, T>\nwhere\n    C: UnindexedConsumer<T>,\n    T: Clone + Send,\n{\n    fn split_off_left(&self) -> Self {\n        let left = IntersperseConsumer {\n            base: self.base.split_off_left(),\n            item: self.item.clone(),\n            clone_first: self.clone_first.clone(),\n        };\n        self.clone_first.set(true);\n        left\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n\nstruct IntersperseFolder<C, T> {\n    base: C,\n    item: T,\n    clone_first: bool,\n}\n\nimpl<C, T> Folder<T> for IntersperseFolder<C, T>\nwhere\n    C: Folder<T>,\n    T: Clone,\n{\n    type Result = C::Result;\n\n    fn consume(mut self, item: T) -> Self {\n        if self.clone_first {\n            self.base = self.base.consume(self.item.clone());\n            if self.base.full() {\n                return self;\n            }\n        } else {\n            self.clone_first = true;\n        }\n        self.base = self.base.consume(item);\n        self\n    }\n\n    fn consume_iter<I>(self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = T>,\n    {\n        let mut clone_first = self.clone_first;\n        let between_item = self.item;\n        let base = self.base.consume_iter(iter.into_iter().flat_map(|item| {\n            let first = if clone_first {\n                Some(between_item.clone())\n            } else {\n                clone_first = true;\n                None\n            };\n            first.into_iter().chain(iter::once(item))\n        }));\n        IntersperseFolder {\n            base,\n            item: between_item,\n            clone_first,\n        }\n    }\n\n    fn complete(self) -> C::Result {\n        self.base.complete()\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n"
  },
  {
    "path": "src/iter/len.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\n/// `MinLen` is an iterator that imposes a minimum length on iterator splits.\n/// This struct is created by the [`with_min_len()`] method on [`IndexedParallelIterator`]\n///\n/// [`with_min_len()`]: IndexedParallelIterator::with_min_len()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\npub struct MinLen<I> {\n    base: I,\n    min: usize,\n}\n\nimpl<I> MinLen<I> {\n    /// Creates a new `MinLen` iterator.\n    pub(super) fn new(base: I, min: usize) -> Self {\n        MinLen { base, min }\n    }\n}\n\nimpl<I> ParallelIterator for MinLen<I>\nwhere\n    I: IndexedParallelIterator,\n{\n    type Item = I::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<I> IndexedParallelIterator for MinLen<I>\nwhere\n    I: IndexedParallelIterator,\n{\n    fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.base.len()\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        return self.base.with_producer(Callback {\n            callback,\n            min: self.min,\n        });\n\n        struct Callback<CB> {\n            callback: CB,\n            min: usize,\n        }\n\n        impl<T, CB> ProducerCallback<T> for Callback<CB>\n        where\n            CB: ProducerCallback<T>,\n        {\n            type Output = CB::Output;\n            fn callback<P>(self, base: P) -> CB::Output\n            where\n                P: Producer<Item = T>,\n            {\n                let producer = MinLenProducer {\n                    base,\n                    min: self.min,\n                };\n                self.callback.callback(producer)\n            }\n        }\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// `MinLenProducer` implementation\n\nstruct MinLenProducer<P> {\n    base: P,\n    min: usize,\n}\n\nimpl<P> Producer for MinLenProducer<P>\nwhere\n    P: Producer,\n{\n    type Item = P::Item;\n    type IntoIter = P::IntoIter;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.base.into_iter()\n    }\n\n    fn min_len(&self) -> usize {\n        Ord::max(self.min, self.base.min_len())\n    }\n\n    fn max_len(&self) -> usize {\n        self.base.max_len()\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let (left, right) = self.base.split_at(index);\n        (\n            MinLenProducer {\n                base: left,\n                min: self.min,\n            },\n            MinLenProducer {\n                base: right,\n                min: self.min,\n            },\n        )\n    }\n\n    fn fold_with<F>(self, folder: F) -> F\n    where\n        F: Folder<Self::Item>,\n    {\n        self.base.fold_with(folder)\n    }\n}\n\n/// `MaxLen` is an iterator that imposes a maximum length on iterator splits.\n/// This struct is created by the [`with_max_len()`] method on [`IndexedParallelIterator`]\n///\n/// [`with_max_len()`]: IndexedParallelIterator::with_max_len()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\npub struct MaxLen<I> {\n    base: I,\n    max: usize,\n}\n\nimpl<I> MaxLen<I> {\n    /// Creates a new `MaxLen` iterator.\n    pub(super) fn new(base: I, max: usize) -> Self {\n        MaxLen { base, max }\n    }\n}\n\nimpl<I> ParallelIterator for MaxLen<I>\nwhere\n    I: IndexedParallelIterator,\n{\n    type Item = I::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<I> IndexedParallelIterator for MaxLen<I>\nwhere\n    I: IndexedParallelIterator,\n{\n    fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.base.len()\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        return self.base.with_producer(Callback {\n            callback,\n            max: self.max,\n        });\n\n        struct Callback<CB> {\n            callback: CB,\n            max: usize,\n        }\n\n        impl<T, CB> ProducerCallback<T> for Callback<CB>\n        where\n            CB: ProducerCallback<T>,\n        {\n            type Output = CB::Output;\n            fn callback<P>(self, base: P) -> CB::Output\n            where\n                P: Producer<Item = T>,\n            {\n                let producer = MaxLenProducer {\n                    base,\n                    max: self.max,\n                };\n                self.callback.callback(producer)\n            }\n        }\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// `MaxLenProducer` implementation\n\nstruct MaxLenProducer<P> {\n    base: P,\n    max: usize,\n}\n\nimpl<P> Producer for MaxLenProducer<P>\nwhere\n    P: Producer,\n{\n    type Item = P::Item;\n    type IntoIter = P::IntoIter;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.base.into_iter()\n    }\n\n    fn min_len(&self) -> usize {\n        self.base.min_len()\n    }\n\n    fn max_len(&self) -> usize {\n        Ord::min(self.max, self.base.max_len())\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let (left, right) = self.base.split_at(index);\n        (\n            MaxLenProducer {\n                base: left,\n                max: self.max,\n            },\n            MaxLenProducer {\n                base: right,\n                max: self.max,\n            },\n        )\n    }\n\n    fn fold_with<F>(self, folder: F) -> F\n    where\n        F: Folder<Self::Item>,\n    {\n        self.base.fold_with(folder)\n    }\n}\n"
  },
  {
    "path": "src/iter/map.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\nuse std::iter;\n\n/// `Map` is an iterator that transforms the elements of an underlying iterator.\n///\n/// This struct is created by the [`map()`] method on [`ParallelIterator`]\n///\n/// [`map()`]: ParallelIterator::map()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Clone)]\npub struct Map<I, F> {\n    base: I,\n    map_op: F,\n}\n\nimpl<I: Debug, F> Debug for Map<I, F> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"Map\").field(\"base\", &self.base).finish()\n    }\n}\n\nimpl<I, F> Map<I, F> {\n    /// Creates a new `Map` iterator.\n    pub(super) fn new(base: I, map_op: F) -> Self {\n        Map { base, map_op }\n    }\n}\n\nimpl<I, F, R> ParallelIterator for Map<I, F>\nwhere\n    I: ParallelIterator,\n    F: Fn(I::Item) -> R + Sync + Send,\n    R: Send,\n{\n    type Item = F::Output;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer1 = MapConsumer::new(consumer, &self.map_op);\n        self.base.drive_unindexed(consumer1)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        self.base.opt_len()\n    }\n}\n\nimpl<I, F, R> IndexedParallelIterator for Map<I, F>\nwhere\n    I: IndexedParallelIterator,\n    F: Fn(I::Item) -> R + Sync + Send,\n    R: Send,\n{\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        let consumer1 = MapConsumer::new(consumer, &self.map_op);\n        self.base.drive(consumer1)\n    }\n\n    fn len(&self) -> usize {\n        self.base.len()\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        return self.base.with_producer(Callback {\n            callback,\n            map_op: self.map_op,\n        });\n\n        struct Callback<CB, F> {\n            callback: CB,\n            map_op: F,\n        }\n\n        impl<T, F, R, CB> ProducerCallback<T> for Callback<CB, F>\n        where\n            CB: ProducerCallback<R>,\n            F: Fn(T) -> R + Sync,\n            R: Send,\n        {\n            type Output = CB::Output;\n\n            fn callback<P>(self, base: P) -> CB::Output\n            where\n                P: Producer<Item = T>,\n            {\n                let producer = MapProducer {\n                    base,\n                    map_op: &self.map_op,\n                };\n                self.callback.callback(producer)\n            }\n        }\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n\nstruct MapProducer<'f, P, F> {\n    base: P,\n    map_op: &'f F,\n}\n\nimpl<'f, P, F, R> Producer for MapProducer<'f, P, F>\nwhere\n    P: Producer,\n    F: Fn(P::Item) -> R + Sync,\n    R: Send,\n{\n    type Item = F::Output;\n    type IntoIter = iter::Map<P::IntoIter, &'f F>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.base.into_iter().map(self.map_op)\n    }\n\n    fn min_len(&self) -> usize {\n        self.base.min_len()\n    }\n    fn max_len(&self) -> usize {\n        self.base.max_len()\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let (left, right) = self.base.split_at(index);\n        (\n            MapProducer {\n                base: left,\n                map_op: self.map_op,\n            },\n            MapProducer {\n                base: right,\n                map_op: self.map_op,\n            },\n        )\n    }\n\n    fn fold_with<G>(self, folder: G) -> G\n    where\n        G: Folder<Self::Item>,\n    {\n        let folder1 = MapFolder {\n            base: folder,\n            map_op: self.map_op,\n        };\n        self.base.fold_with(folder1).base\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Consumer implementation\n\nstruct MapConsumer<'f, C, F> {\n    base: C,\n    map_op: &'f F,\n}\n\nimpl<'f, C, F> MapConsumer<'f, C, F> {\n    fn new(base: C, map_op: &'f F) -> Self {\n        MapConsumer { base, map_op }\n    }\n}\n\nimpl<'f, T, R, C, F> Consumer<T> for MapConsumer<'f, C, F>\nwhere\n    C: Consumer<F::Output>,\n    F: Fn(T) -> R + Sync,\n    R: Send,\n{\n    type Folder = MapFolder<'f, C::Folder, F>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            MapConsumer::new(left, self.map_op),\n            MapConsumer::new(right, self.map_op),\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        MapFolder {\n            base: self.base.into_folder(),\n            map_op: self.map_op,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\nimpl<'f, T, R, C, F> UnindexedConsumer<T> for MapConsumer<'f, C, F>\nwhere\n    C: UnindexedConsumer<F::Output>,\n    F: Fn(T) -> R + Sync,\n    R: Send,\n{\n    fn split_off_left(&self) -> Self {\n        MapConsumer::new(self.base.split_off_left(), self.map_op)\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n\nstruct MapFolder<'f, C, F> {\n    base: C,\n    map_op: &'f F,\n}\n\nimpl<'f, T, R, C, F> Folder<T> for MapFolder<'f, C, F>\nwhere\n    C: Folder<F::Output>,\n    F: Fn(T) -> R,\n{\n    type Result = C::Result;\n\n    fn consume(self, item: T) -> Self {\n        let mapped_item = (self.map_op)(item);\n        MapFolder {\n            base: self.base.consume(mapped_item),\n            map_op: self.map_op,\n        }\n    }\n\n    fn consume_iter<I>(mut self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = T>,\n    {\n        self.base = self.base.consume_iter(iter.into_iter().map(self.map_op));\n        self\n    }\n\n    fn complete(self) -> C::Result {\n        self.base.complete()\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n"
  },
  {
    "path": "src/iter/map_with.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\n\n/// `MapWith` is an iterator that transforms the elements of an underlying iterator.\n///\n/// This struct is created by the [`map_with()`] method on [`ParallelIterator`]\n///\n/// [`map_with()`]: ParallelIterator::map_with()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Clone)]\npub struct MapWith<I, T, F> {\n    base: I,\n    item: T,\n    map_op: F,\n}\n\nimpl<I: Debug, T: Debug, F> Debug for MapWith<I, T, F> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"MapWith\")\n            .field(\"base\", &self.base)\n            .field(\"item\", &self.item)\n            .finish()\n    }\n}\n\nimpl<I, T, F> MapWith<I, T, F> {\n    /// Creates a new `MapWith` iterator.\n    pub(super) fn new(base: I, item: T, map_op: F) -> Self {\n        MapWith { base, item, map_op }\n    }\n}\n\nimpl<I, T, F, R> ParallelIterator for MapWith<I, T, F>\nwhere\n    I: ParallelIterator,\n    T: Send + Clone,\n    F: Fn(&mut T, I::Item) -> R + Sync + Send,\n    R: Send,\n{\n    type Item = R;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer1 = MapWithConsumer::new(consumer, self.item, &self.map_op);\n        self.base.drive_unindexed(consumer1)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        self.base.opt_len()\n    }\n}\n\nimpl<I, T, F, R> IndexedParallelIterator for MapWith<I, T, F>\nwhere\n    I: IndexedParallelIterator,\n    T: Send + Clone,\n    F: Fn(&mut T, I::Item) -> R + Sync + Send,\n    R: Send,\n{\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        let consumer1 = MapWithConsumer::new(consumer, self.item, &self.map_op);\n        self.base.drive(consumer1)\n    }\n\n    fn len(&self) -> usize {\n        self.base.len()\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        return self.base.with_producer(Callback {\n            callback,\n            item: self.item,\n            map_op: self.map_op,\n        });\n\n        struct Callback<CB, U, F> {\n            callback: CB,\n            item: U,\n            map_op: F,\n        }\n\n        impl<T, U, F, R, CB> ProducerCallback<T> for Callback<CB, U, F>\n        where\n            CB: ProducerCallback<R>,\n            U: Send + Clone,\n            F: Fn(&mut U, T) -> R + Sync,\n            R: Send,\n        {\n            type Output = CB::Output;\n\n            fn callback<P>(self, base: P) -> CB::Output\n            where\n                P: Producer<Item = T>,\n            {\n                let producer = MapWithProducer {\n                    base,\n                    item: self.item,\n                    map_op: &self.map_op,\n                };\n                self.callback.callback(producer)\n            }\n        }\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n\nstruct MapWithProducer<'f, P, U, F> {\n    base: P,\n    item: U,\n    map_op: &'f F,\n}\n\nimpl<'f, P, U, F, R> Producer for MapWithProducer<'f, P, U, F>\nwhere\n    P: Producer,\n    U: Send + Clone,\n    F: Fn(&mut U, P::Item) -> R + Sync,\n    R: Send,\n{\n    type Item = R;\n    type IntoIter = MapWithIter<'f, P::IntoIter, U, F>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        MapWithIter {\n            base: self.base.into_iter(),\n            item: self.item,\n            map_op: self.map_op,\n        }\n    }\n\n    fn min_len(&self) -> usize {\n        self.base.min_len()\n    }\n    fn max_len(&self) -> usize {\n        self.base.max_len()\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let (left, right) = self.base.split_at(index);\n        (\n            MapWithProducer {\n                base: left,\n                item: self.item.clone(),\n                map_op: self.map_op,\n            },\n            MapWithProducer {\n                base: right,\n                item: self.item,\n                map_op: self.map_op,\n            },\n        )\n    }\n\n    fn fold_with<G>(self, folder: G) -> G\n    where\n        G: Folder<Self::Item>,\n    {\n        let folder1 = MapWithFolder {\n            base: folder,\n            item: self.item,\n            map_op: self.map_op,\n        };\n        self.base.fold_with(folder1).base\n    }\n}\n\nstruct MapWithIter<'f, I, U, F> {\n    base: I,\n    item: U,\n    map_op: &'f F,\n}\n\nimpl<'f, I, U, F, R> Iterator for MapWithIter<'f, I, U, F>\nwhere\n    I: Iterator,\n    F: Fn(&mut U, I::Item) -> R + Sync,\n    R: Send,\n{\n    type Item = R;\n\n    fn next(&mut self) -> Option<R> {\n        let item = self.base.next()?;\n        Some((self.map_op)(&mut self.item, item))\n    }\n\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        self.base.size_hint()\n    }\n}\n\nimpl<'f, I, U, F, R> DoubleEndedIterator for MapWithIter<'f, I, U, F>\nwhere\n    I: DoubleEndedIterator,\n    F: Fn(&mut U, I::Item) -> R + Sync,\n    R: Send,\n{\n    fn next_back(&mut self) -> Option<R> {\n        let item = self.base.next_back()?;\n        Some((self.map_op)(&mut self.item, item))\n    }\n}\n\nimpl<'f, I, U, F, R> ExactSizeIterator for MapWithIter<'f, I, U, F>\nwhere\n    I: ExactSizeIterator,\n    F: Fn(&mut U, I::Item) -> R + Sync,\n    R: Send,\n{\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Consumer implementation\n\nstruct MapWithConsumer<'f, C, U, F> {\n    base: C,\n    item: U,\n    map_op: &'f F,\n}\n\nimpl<'f, C, U, F> MapWithConsumer<'f, C, U, F> {\n    fn new(base: C, item: U, map_op: &'f F) -> Self {\n        MapWithConsumer { base, item, map_op }\n    }\n}\n\nimpl<'f, T, U, R, C, F> Consumer<T> for MapWithConsumer<'f, C, U, F>\nwhere\n    C: Consumer<R>,\n    U: Send + Clone,\n    F: Fn(&mut U, T) -> R + Sync,\n    R: Send,\n{\n    type Folder = MapWithFolder<'f, C::Folder, U, F>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            MapWithConsumer::new(left, self.item.clone(), self.map_op),\n            MapWithConsumer::new(right, self.item, self.map_op),\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        MapWithFolder {\n            base: self.base.into_folder(),\n            item: self.item,\n            map_op: self.map_op,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\nimpl<'f, T, U, R, C, F> UnindexedConsumer<T> for MapWithConsumer<'f, C, U, F>\nwhere\n    C: UnindexedConsumer<R>,\n    U: Send + Clone,\n    F: Fn(&mut U, T) -> R + Sync,\n    R: Send,\n{\n    fn split_off_left(&self) -> Self {\n        MapWithConsumer::new(self.base.split_off_left(), self.item.clone(), self.map_op)\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n\nstruct MapWithFolder<'f, C, U, F> {\n    base: C,\n    item: U,\n    map_op: &'f F,\n}\n\nimpl<'f, T, U, R, C, F> Folder<T> for MapWithFolder<'f, C, U, F>\nwhere\n    C: Folder<R>,\n    F: Fn(&mut U, T) -> R,\n{\n    type Result = C::Result;\n\n    fn consume(mut self, item: T) -> Self {\n        let mapped_item = (self.map_op)(&mut self.item, item);\n        self.base = self.base.consume(mapped_item);\n        self\n    }\n\n    fn consume_iter<I>(mut self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = T>,\n    {\n        fn with<'f, T, U, R>(\n            item: &'f mut U,\n            map_op: impl Fn(&mut U, T) -> R + 'f,\n        ) -> impl FnMut(T) -> R + 'f {\n            move |x| map_op(item, x)\n        }\n\n        {\n            let mapped_iter = iter.into_iter().map(with(&mut self.item, self.map_op));\n            self.base = self.base.consume_iter(mapped_iter);\n        }\n        self\n    }\n\n    fn complete(self) -> C::Result {\n        self.base.complete()\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\n// ------------------------------------------------------------------------------------------------\n\n/// `MapInit` is an iterator that transforms the elements of an underlying iterator.\n///\n/// This struct is created by the [`map_init()`] method on [`ParallelIterator`]\n///\n/// [`map_init()`]: ParallelIterator::map_init()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Clone)]\npub struct MapInit<I, INIT, F> {\n    base: I,\n    init: INIT,\n    map_op: F,\n}\n\nimpl<I: Debug, INIT, F> Debug for MapInit<I, INIT, F> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"MapInit\").field(\"base\", &self.base).finish()\n    }\n}\n\nimpl<I, INIT, F> MapInit<I, INIT, F> {\n    /// Creates a new `MapInit` iterator.\n    pub(super) fn new(base: I, init: INIT, map_op: F) -> Self {\n        MapInit { base, init, map_op }\n    }\n}\n\nimpl<I, INIT, T, F, R> ParallelIterator for MapInit<I, INIT, F>\nwhere\n    I: ParallelIterator,\n    INIT: Fn() -> T + Sync + Send,\n    F: Fn(&mut T, I::Item) -> R + Sync + Send,\n    R: Send,\n{\n    type Item = R;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer1 = MapInitConsumer::new(consumer, &self.init, &self.map_op);\n        self.base.drive_unindexed(consumer1)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        self.base.opt_len()\n    }\n}\n\nimpl<I, INIT, T, F, R> IndexedParallelIterator for MapInit<I, INIT, F>\nwhere\n    I: IndexedParallelIterator,\n    INIT: Fn() -> T + Sync + Send,\n    F: Fn(&mut T, I::Item) -> R + Sync + Send,\n    R: Send,\n{\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        let consumer1 = MapInitConsumer::new(consumer, &self.init, &self.map_op);\n        self.base.drive(consumer1)\n    }\n\n    fn len(&self) -> usize {\n        self.base.len()\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        return self.base.with_producer(Callback {\n            callback,\n            init: self.init,\n            map_op: self.map_op,\n        });\n\n        struct Callback<CB, INIT, F> {\n            callback: CB,\n            init: INIT,\n            map_op: F,\n        }\n\n        impl<T, INIT, U, F, R, CB> ProducerCallback<T> for Callback<CB, INIT, F>\n        where\n            CB: ProducerCallback<R>,\n            INIT: Fn() -> U + Sync,\n            F: Fn(&mut U, T) -> R + Sync,\n            R: Send,\n        {\n            type Output = CB::Output;\n\n            fn callback<P>(self, base: P) -> CB::Output\n            where\n                P: Producer<Item = T>,\n            {\n                let producer = MapInitProducer {\n                    base,\n                    init: &self.init,\n                    map_op: &self.map_op,\n                };\n                self.callback.callback(producer)\n            }\n        }\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n\nstruct MapInitProducer<'f, P, INIT, F> {\n    base: P,\n    init: &'f INIT,\n    map_op: &'f F,\n}\n\nimpl<'f, P, INIT, U, F, R> Producer for MapInitProducer<'f, P, INIT, F>\nwhere\n    P: Producer,\n    INIT: Fn() -> U + Sync,\n    F: Fn(&mut U, P::Item) -> R + Sync,\n    R: Send,\n{\n    type Item = R;\n    type IntoIter = MapWithIter<'f, P::IntoIter, U, F>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        MapWithIter {\n            base: self.base.into_iter(),\n            item: (self.init)(),\n            map_op: self.map_op,\n        }\n    }\n\n    fn min_len(&self) -> usize {\n        self.base.min_len()\n    }\n    fn max_len(&self) -> usize {\n        self.base.max_len()\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let (left, right) = self.base.split_at(index);\n        (\n            MapInitProducer {\n                base: left,\n                init: self.init,\n                map_op: self.map_op,\n            },\n            MapInitProducer {\n                base: right,\n                init: self.init,\n                map_op: self.map_op,\n            },\n        )\n    }\n\n    fn fold_with<G>(self, folder: G) -> G\n    where\n        G: Folder<Self::Item>,\n    {\n        let folder1 = MapWithFolder {\n            base: folder,\n            item: (self.init)(),\n            map_op: self.map_op,\n        };\n        self.base.fold_with(folder1).base\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Consumer implementation\n\nstruct MapInitConsumer<'f, C, INIT, F> {\n    base: C,\n    init: &'f INIT,\n    map_op: &'f F,\n}\n\nimpl<'f, C, INIT, F> MapInitConsumer<'f, C, INIT, F> {\n    fn new(base: C, init: &'f INIT, map_op: &'f F) -> Self {\n        MapInitConsumer { base, init, map_op }\n    }\n}\n\nimpl<'f, T, INIT, U, R, C, F> Consumer<T> for MapInitConsumer<'f, C, INIT, F>\nwhere\n    C: Consumer<R>,\n    INIT: Fn() -> U + Sync,\n    F: Fn(&mut U, T) -> R + Sync,\n    R: Send,\n{\n    type Folder = MapWithFolder<'f, C::Folder, U, F>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            MapInitConsumer::new(left, self.init, self.map_op),\n            MapInitConsumer::new(right, self.init, self.map_op),\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        MapWithFolder {\n            base: self.base.into_folder(),\n            item: (self.init)(),\n            map_op: self.map_op,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\nimpl<'f, T, INIT, U, R, C, F> UnindexedConsumer<T> for MapInitConsumer<'f, C, INIT, F>\nwhere\n    C: UnindexedConsumer<R>,\n    INIT: Fn() -> U + Sync,\n    F: Fn(&mut U, T) -> R + Sync,\n    R: Send,\n{\n    fn split_off_left(&self) -> Self {\n        MapInitConsumer::new(self.base.split_off_left(), self.init, self.map_op)\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n"
  },
  {
    "path": "src/iter/mod.rs",
    "content": "//! Traits for writing parallel programs using an iterator-style interface\n//!\n//! You will rarely need to interact with this module directly unless you have\n//! need to name one of the iterator types.\n//!\n//! Parallel iterators make it easy to write iterator-like chains that\n//! execute in parallel: typically all you have to do is convert the\n//! first `.iter()` (or `iter_mut()`, `into_iter()`, etc) method into\n//! `par_iter()` (or `par_iter_mut()`, `into_par_iter()`, etc). For\n//! example, to compute the sum of the squares of a sequence of\n//! integers, one might write:\n//!\n//! ```rust\n//! use rayon::prelude::*;\n//! fn sum_of_squares(input: &[i32]) -> i32 {\n//!     input.par_iter()\n//!          .map(|i| i * i)\n//!          .sum()\n//! }\n//! ```\n//!\n//! Or, to increment all the integers in a slice, you could write:\n//!\n//! ```rust\n//! use rayon::prelude::*;\n//! fn increment_all(input: &mut [i32]) {\n//!     input.par_iter_mut()\n//!          .for_each(|p| *p += 1);\n//! }\n//! ```\n//!\n//! To use parallel iterators, first import the traits by adding\n//! something like `use rayon::prelude::*` to your module. You can\n//! then call `par_iter`, `par_iter_mut`, or `into_par_iter` to get a\n//! parallel iterator. Like a [regular iterator][], parallel\n//! iterators work by first constructing a computation and then\n//! executing it.\n//!\n//! In addition to `par_iter()` and friends, some types offer other\n//! ways to create (or consume) parallel iterators:\n//!\n//! - Slices (`&[T]`, `&mut [T]`) offer methods like `par_split` and\n//!   `par_windows`, as well as various parallel sorting\n//!   operations. See [the `ParallelSlice` trait] for the full list.\n//! - Strings (`&str`) offer methods like `par_split` and `par_lines`.\n//!   See [the `ParallelString` trait] for the full list.\n//! - Various collections offer [`par_extend`], which grows a\n//!   collection given a parallel iterator. (If you don't have a\n//!   collection to extend, you can use [`collect()`] to create a new\n//!   one from scratch.)\n//!\n//! [the `ParallelSlice` trait]: crate::slice::ParallelSlice\n//! [the `ParallelString` trait]: crate::str::ParallelString\n//! [`par_extend`]: ParallelExtend\n//! [`collect()`]: ParallelIterator::collect()\n//!\n//! To see the full range of methods available on parallel iterators,\n//! check out the [`ParallelIterator`] and [`IndexedParallelIterator`]\n//! traits.\n//!\n//! If you'd like to build a custom parallel iterator, or to write your own\n//! combinator, then check out the [split] function and the [plumbing] module.\n//!\n//! [regular iterator]: Iterator\n//! [split]: split()\n//! [plumbing]: plumbing\n//!\n//! Note: Several of the `ParallelIterator` methods rely on a `Try` trait which\n//! has been deliberately obscured from the public API.  This trait is intended\n//! to mirror the unstable `std::ops::Try` with implementations for `Option` and\n//! `Result`, where `Some`/`Ok` values will let those iterators continue, but\n//! `None`/`Err` values will exit early.\n//!\n//! A note about\n//! [dyn compatiblity](https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility):\n//! It is currently _not_ possible to wrap a `ParallelIterator` (or any trait\n//! that depends on it) using a `Box<dyn ParallelIterator>` or other kind of\n//! dynamic allocation, because `ParallelIterator` is **not dyn-compatible**.\n//! (This keeps the implementation simpler and allows extra optimizations.)\n\nuse self::plumbing::*;\nuse self::private::Try;\npub use either::Either;\nuse std::cmp::Ordering;\nuse std::collections::LinkedList;\nuse std::iter::{Product, Sum};\nuse std::ops::{Fn, RangeBounds};\n\npub mod plumbing;\n\n#[cfg(test)]\nmod test;\n\n// There is a method to the madness here:\n//\n// - These modules are private but expose certain types to the end-user\n//   (e.g., `enumerate::Enumerate`) -- specifically, the types that appear in the\n//   public API surface of the `ParallelIterator` traits.\n// - In **this** module, those public types are always used unprefixed, which forces\n//   us to add a `pub use` and helps identify if we missed anything.\n// - In contrast, items that appear **only** in the body of a method,\n//   e.g. `find::find()`, are always used **prefixed**, so that they\n//   can be readily distinguished.\n\nmod blocks;\nmod chain;\nmod chunks;\nmod cloned;\nmod collect;\nmod copied;\nmod empty;\nmod enumerate;\nmod extend;\nmod filter;\nmod filter_map;\nmod find;\nmod find_first_last;\nmod flat_map;\nmod flat_map_iter;\nmod flatten;\nmod flatten_iter;\nmod fold;\nmod fold_chunks;\nmod fold_chunks_with;\nmod for_each;\nmod from_par_iter;\nmod inspect;\nmod interleave;\nmod interleave_shortest;\nmod intersperse;\nmod len;\nmod map;\nmod map_with;\nmod multizip;\nmod noop;\nmod once;\nmod panic_fuse;\nmod par_bridge;\nmod positions;\nmod product;\nmod reduce;\nmod repeat;\nmod rev;\nmod skip;\nmod skip_any;\nmod skip_any_while;\nmod splitter;\nmod step_by;\nmod sum;\nmod take;\nmod take_any;\nmod take_any_while;\nmod try_fold;\nmod try_reduce;\nmod try_reduce_with;\nmod unzip;\nmod update;\nmod walk_tree;\nmod while_some;\nmod zip;\nmod zip_eq;\n\npub use self::{\n    blocks::{ExponentialBlocks, UniformBlocks},\n    chain::Chain,\n    chunks::Chunks,\n    cloned::Cloned,\n    copied::Copied,\n    empty::{empty, Empty},\n    enumerate::Enumerate,\n    filter::Filter,\n    filter_map::FilterMap,\n    flat_map::FlatMap,\n    flat_map_iter::FlatMapIter,\n    flatten::Flatten,\n    flatten_iter::FlattenIter,\n    fold::{Fold, FoldWith},\n    fold_chunks::FoldChunks,\n    fold_chunks_with::FoldChunksWith,\n    inspect::Inspect,\n    interleave::Interleave,\n    interleave_shortest::InterleaveShortest,\n    intersperse::Intersperse,\n    len::{MaxLen, MinLen},\n    map::Map,\n    map_with::{MapInit, MapWith},\n    multizip::MultiZip,\n    once::{once, Once},\n    panic_fuse::PanicFuse,\n    par_bridge::{IterBridge, ParallelBridge},\n    positions::Positions,\n    repeat::{repeat, repeat_n, Repeat, RepeatN},\n    rev::Rev,\n    skip::Skip,\n    skip_any::SkipAny,\n    skip_any_while::SkipAnyWhile,\n    splitter::{split, Split},\n    step_by::StepBy,\n    take::Take,\n    take_any::TakeAny,\n    take_any_while::TakeAnyWhile,\n    try_fold::{TryFold, TryFoldWith},\n    update::Update,\n    walk_tree::{\n        walk_tree, walk_tree_postfix, walk_tree_prefix, WalkTree, WalkTreePostfix, WalkTreePrefix,\n    },\n    while_some::WhileSome,\n    zip::Zip,\n    zip_eq::ZipEq,\n};\n\n#[allow(deprecated)]\npub use repeat::repeatn;\n\n/// `IntoParallelIterator` implements the conversion to a [`ParallelIterator`].\n///\n/// By implementing `IntoParallelIterator` for a type, you define how it will\n/// transformed into an iterator. This is a parallel version of the standard\n/// library's [`std::iter::IntoIterator`] trait.\npub trait IntoParallelIterator {\n    /// The parallel iterator type that will be created.\n    type Iter: ParallelIterator<Item = Self::Item>;\n\n    /// The type of item that the parallel iterator will produce.\n    type Item: Send;\n\n    /// Converts `self` into a parallel iterator.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// println!(\"counting in parallel:\");\n    /// (0..100).into_par_iter()\n    ///     .for_each(|i| println!(\"{}\", i));\n    /// ```\n    ///\n    /// This conversion is often implicit for arguments to methods like [`zip`].\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let v: Vec<_> = (0..5).into_par_iter().zip(5..10).collect();\n    /// assert_eq!(v, [(0, 5), (1, 6), (2, 7), (3, 8), (4, 9)]);\n    /// ```\n    ///\n    /// [`zip`]: IndexedParallelIterator::zip()\n    fn into_par_iter(self) -> Self::Iter;\n}\n\n/// `IntoParallelRefIterator` implements the conversion to a\n/// [`ParallelIterator`], providing shared references to the data.\n///\n/// This is a parallel version of the `iter()` method\n/// defined by various collections.\n///\n/// This trait is automatically implemented\n/// `for I where &I: IntoParallelIterator`. In most cases, users\n/// will want to implement [`IntoParallelIterator`] rather than implement\n/// this trait directly.\npub trait IntoParallelRefIterator<'data> {\n    /// The type of the parallel iterator that will be returned.\n    type Iter: ParallelIterator<Item = Self::Item>;\n\n    /// The type of item that the parallel iterator will produce.\n    /// This will typically be an `&'data T` reference type.\n    type Item: Send + 'data;\n\n    /// Converts `self` into a parallel iterator.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let v: Vec<_> = (0..100).collect();\n    /// assert_eq!(v.par_iter().sum::<i32>(), 100 * 99 / 2);\n    ///\n    /// // `v.par_iter()` is shorthand for `(&v).into_par_iter()`,\n    /// // producing the exact same references.\n    /// assert!(v.par_iter().zip(&v)\n    ///          .all(|(a, b)| std::ptr::eq(a, b)));\n    /// ```\n    fn par_iter(&'data self) -> Self::Iter;\n}\n\nimpl<'data, I: 'data + ?Sized> IntoParallelRefIterator<'data> for I\nwhere\n    &'data I: IntoParallelIterator,\n{\n    type Iter = <&'data I as IntoParallelIterator>::Iter;\n    type Item = <&'data I as IntoParallelIterator>::Item;\n\n    fn par_iter(&'data self) -> Self::Iter {\n        self.into_par_iter()\n    }\n}\n\n/// `IntoParallelRefMutIterator` implements the conversion to a\n/// [`ParallelIterator`], providing mutable references to the data.\n///\n/// This is a parallel version of the `iter_mut()` method\n/// defined by various collections.\n///\n/// This trait is automatically implemented\n/// `for I where &mut I: IntoParallelIterator`. In most cases, users\n/// will want to implement [`IntoParallelIterator`] rather than implement\n/// this trait directly.\npub trait IntoParallelRefMutIterator<'data> {\n    /// The type of iterator that will be created.\n    type Iter: ParallelIterator<Item = Self::Item>;\n\n    /// The type of item that will be produced; this is typically an\n    /// `&'data mut T` reference.\n    type Item: Send + 'data;\n\n    /// Creates the parallel iterator from `self`.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let mut v = vec![0usize; 5];\n    /// v.par_iter_mut().enumerate().for_each(|(i, x)| *x = i);\n    /// assert_eq!(v, [0, 1, 2, 3, 4]);\n    /// ```\n    fn par_iter_mut(&'data mut self) -> Self::Iter;\n}\n\nimpl<'data, I: 'data + ?Sized> IntoParallelRefMutIterator<'data> for I\nwhere\n    &'data mut I: IntoParallelIterator,\n{\n    type Iter = <&'data mut I as IntoParallelIterator>::Iter;\n    type Item = <&'data mut I as IntoParallelIterator>::Item;\n\n    fn par_iter_mut(&'data mut self) -> Self::Iter {\n        self.into_par_iter()\n    }\n}\n\n/// Parallel version of the standard iterator trait.\n///\n/// The combinators on this trait are available on **all** parallel\n/// iterators.  Additional methods can be found on the\n/// [`IndexedParallelIterator`] trait: those methods are only\n/// available for parallel iterators where the number of items is\n/// known in advance (so, e.g., after invoking `filter`, those methods\n/// become unavailable).\n///\n/// For examples of using parallel iterators, see [the docs on the\n/// `iter` module][iter].\n///\n/// [iter]: self\npub trait ParallelIterator: Sized + Send {\n    /// The type of item that this parallel iterator produces.\n    /// For example, if you use the [`for_each`] method, this is the type of\n    /// item that your closure will be invoked with.\n    ///\n    /// [`for_each`]: #method.for_each\n    type Item: Send;\n\n    /// Executes `OP` on each item produced by the iterator, in parallel.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// (0..100).into_par_iter().for_each(|x| println!(\"{:?}\", x));\n    /// ```\n    fn for_each<OP>(self, op: OP)\n    where\n        OP: Fn(Self::Item) + Sync + Send,\n    {\n        for_each::for_each(self, &op)\n    }\n\n    /// Executes `OP` on the given `init` value with each item produced by\n    /// the iterator, in parallel.\n    ///\n    /// The `init` value will be cloned only as needed to be paired with\n    /// the group of items in each rayon job.  It does not require the type\n    /// to be `Sync`.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use std::sync::mpsc::channel;\n    /// use rayon::prelude::*;\n    ///\n    /// let (sender, receiver) = channel();\n    ///\n    /// (0..5).into_par_iter().for_each_with(sender, |s, x| s.send(x).unwrap());\n    ///\n    /// let mut res: Vec<_> = receiver.iter().collect();\n    ///\n    /// res.sort();\n    ///\n    /// assert_eq!(&res[..], &[0, 1, 2, 3, 4])\n    /// ```\n    fn for_each_with<OP, T>(self, init: T, op: OP)\n    where\n        OP: Fn(&mut T, Self::Item) + Sync + Send,\n        T: Send + Clone,\n    {\n        self.map_with(init, op).collect()\n    }\n\n    /// Executes `OP` on a value returned by `init` with each item produced by\n    /// the iterator, in parallel.\n    ///\n    /// The `init` function will be called only as needed for a value to be\n    /// paired with the group of items in each rayon job.  There is no\n    /// constraint on that returned type at all!\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rand::Rng;\n    /// use rayon::prelude::*;\n    ///\n    /// let mut v = vec![0u8; 1_000_000];\n    ///\n    /// v.par_chunks_mut(1000)\n    ///     .for_each_init(\n    ///         || rand::rng(),\n    ///         |rng, chunk| rng.fill(chunk),\n    ///     );\n    ///\n    /// // There's a remote chance that this will fail...\n    /// for i in 0u8..=255 {\n    ///     assert!(v.contains(&i));\n    /// }\n    /// ```\n    fn for_each_init<OP, INIT, T>(self, init: INIT, op: OP)\n    where\n        OP: Fn(&mut T, Self::Item) + Sync + Send,\n        INIT: Fn() -> T + Sync + Send,\n    {\n        self.map_init(init, op).collect()\n    }\n\n    /// Executes a fallible `OP` on each item produced by the iterator, in parallel.\n    ///\n    /// If the `OP` returns `Result::Err` or `Option::None`, we will attempt to\n    /// stop processing the rest of the items in the iterator as soon as\n    /// possible, and we will return that terminating value.  Otherwise, we will\n    /// return an empty `Result::Ok(())` or `Option::Some(())`.  If there are\n    /// multiple errors in parallel, it is not specified which will be returned.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// use std::io::{self, Write};\n    ///\n    /// // This will stop iteration early if there's any write error, like\n    /// // having piped output get closed on the other end.\n    /// (0..100).into_par_iter()\n    ///     .try_for_each(|x| writeln!(io::stdout(), \"{:?}\", x))\n    ///     .expect(\"expected no write errors\");\n    /// ```\n    fn try_for_each<OP, R>(self, op: OP) -> R\n    where\n        OP: Fn(Self::Item) -> R + Sync + Send,\n        R: Try<Output = ()> + Send,\n    {\n        fn ok<R: Try<Output = ()>>(_: (), _: ()) -> R {\n            R::from_output(())\n        }\n\n        self.map(op).try_reduce(<()>::default, ok)\n    }\n\n    /// Executes a fallible `OP` on the given `init` value with each item\n    /// produced by the iterator, in parallel.\n    ///\n    /// This combines the `init` semantics of [`for_each_with()`] and the\n    /// failure semantics of [`try_for_each()`].\n    ///\n    /// [`for_each_with()`]: #method.for_each_with\n    /// [`try_for_each()`]: #method.try_for_each\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use std::sync::mpsc::channel;\n    /// use rayon::prelude::*;\n    ///\n    /// let (sender, receiver) = channel();\n    ///\n    /// (0..5).into_par_iter()\n    ///     .try_for_each_with(sender, |s, x| s.send(x))\n    ///     .expect(\"expected no send errors\");\n    ///\n    /// let mut res: Vec<_> = receiver.iter().collect();\n    ///\n    /// res.sort();\n    ///\n    /// assert_eq!(&res[..], &[0, 1, 2, 3, 4])\n    /// ```\n    fn try_for_each_with<OP, T, R>(self, init: T, op: OP) -> R\n    where\n        OP: Fn(&mut T, Self::Item) -> R + Sync + Send,\n        T: Send + Clone,\n        R: Try<Output = ()> + Send,\n    {\n        fn ok<R: Try<Output = ()>>(_: (), _: ()) -> R {\n            R::from_output(())\n        }\n\n        self.map_with(init, op).try_reduce(<()>::default, ok)\n    }\n\n    /// Executes a fallible `OP` on a value returned by `init` with each item\n    /// produced by the iterator, in parallel.\n    ///\n    /// This combines the `init` semantics of [`for_each_init()`] and the\n    /// failure semantics of [`try_for_each()`].\n    ///\n    /// [`for_each_init()`]: #method.for_each_init\n    /// [`try_for_each()`]: #method.try_for_each\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rand::{Rng, TryRngCore};\n    /// use rayon::prelude::*;\n    ///\n    /// let mut v = vec![0u8; 1_000_000];\n    ///\n    /// v.par_chunks_mut(1000)\n    ///     .try_for_each_init(\n    ///         || rand::rng(),\n    ///         |rng, chunk| rng.try_fill_bytes(chunk),\n    ///     )\n    ///     .expect(\"expected no rand errors\");\n    ///\n    /// // There's a remote chance that this will fail...\n    /// for i in 0u8..=255 {\n    ///     assert!(v.contains(&i));\n    /// }\n    /// ```\n    fn try_for_each_init<OP, INIT, T, R>(self, init: INIT, op: OP) -> R\n    where\n        OP: Fn(&mut T, Self::Item) -> R + Sync + Send,\n        INIT: Fn() -> T + Sync + Send,\n        R: Try<Output = ()> + Send,\n    {\n        fn ok<R: Try<Output = ()>>(_: (), _: ()) -> R {\n            R::from_output(())\n        }\n\n        self.map_init(init, op).try_reduce(<()>::default, ok)\n    }\n\n    /// Counts the number of items in this parallel iterator.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let count = (0..100).into_par_iter().count();\n    ///\n    /// assert_eq!(count, 100);\n    /// ```\n    fn count(self) -> usize {\n        fn one<T>(_: T) -> usize {\n            1\n        }\n\n        self.map(one).sum()\n    }\n\n    /// Applies `map_op` to each item of this iterator, producing a new\n    /// iterator with the results.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let mut par_iter = (0..5).into_par_iter().map(|x| x * 2);\n    ///\n    /// let doubles: Vec<_> = par_iter.collect();\n    ///\n    /// assert_eq!(&doubles[..], &[0, 2, 4, 6, 8]);\n    /// ```\n    fn map<F, R>(self, map_op: F) -> Map<Self, F>\n    where\n        F: Fn(Self::Item) -> R + Sync + Send,\n        R: Send,\n    {\n        Map::new(self, map_op)\n    }\n\n    /// Applies `map_op` to the given `init` value with each item of this\n    /// iterator, producing a new iterator with the results.\n    ///\n    /// The `init` value will be cloned only as needed to be paired with\n    /// the group of items in each rayon job.  It does not require the type\n    /// to be `Sync`.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use std::sync::mpsc::channel;\n    /// use rayon::prelude::*;\n    ///\n    /// let (sender, receiver) = channel();\n    ///\n    /// let a: Vec<_> = (0..5)\n    ///                 .into_par_iter()            // iterating over i32\n    ///                 .map_with(sender, |s, x| {\n    ///                     s.send(x).unwrap();     // sending i32 values through the channel\n    ///                     x                       // returning i32\n    ///                 })\n    ///                 .collect();                 // collecting the returned values into a vector\n    ///\n    /// let mut b: Vec<_> = receiver.iter()         // iterating over the values in the channel\n    ///                             .collect();     // and collecting them\n    /// b.sort();\n    ///\n    /// assert_eq!(a, b);\n    /// ```\n    fn map_with<F, T, R>(self, init: T, map_op: F) -> MapWith<Self, T, F>\n    where\n        F: Fn(&mut T, Self::Item) -> R + Sync + Send,\n        T: Send + Clone,\n        R: Send,\n    {\n        MapWith::new(self, init, map_op)\n    }\n\n    /// Applies `map_op` to a value returned by `init` with each item of this\n    /// iterator, producing a new iterator with the results.\n    ///\n    /// The `init` function will be called only as needed for a value to be\n    /// paired with the group of items in each rayon job.  There is no\n    /// constraint on that returned type at all!\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rand::Rng;\n    /// use rayon::prelude::*;\n    ///\n    /// let a: Vec<_> = (1i32..1_000_000)\n    ///     .into_par_iter()\n    ///     .map_init(\n    ///         || rand::rng(),  // get the thread-local RNG\n    ///         |rng, x| if rng.random() { // randomly negate items\n    ///             -x\n    ///         } else {\n    ///             x\n    ///         },\n    ///     ).collect();\n    ///\n    /// // There's a remote chance that this will fail...\n    /// assert!(a.iter().any(|&x| x < 0));\n    /// assert!(a.iter().any(|&x| x > 0));\n    /// ```\n    fn map_init<F, INIT, T, R>(self, init: INIT, map_op: F) -> MapInit<Self, INIT, F>\n    where\n        F: Fn(&mut T, Self::Item) -> R + Sync + Send,\n        INIT: Fn() -> T + Sync + Send,\n        R: Send,\n    {\n        MapInit::new(self, init, map_op)\n    }\n\n    /// Creates an iterator which clones all of its elements.  This may be\n    /// useful when you have an iterator over `&T`, but you need `T`, and\n    /// that type implements `Clone`. See also [`copied()`].\n    ///\n    /// [`copied()`]: #method.copied\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [1, 2, 3];\n    ///\n    /// let v_cloned: Vec<_> = a.par_iter().cloned().collect();\n    ///\n    /// // cloned is the same as .map(|&x| x), for integers\n    /// let v_map: Vec<_> = a.par_iter().map(|&x| x).collect();\n    ///\n    /// assert_eq!(v_cloned, vec![1, 2, 3]);\n    /// assert_eq!(v_map, vec![1, 2, 3]);\n    /// ```\n    fn cloned<'a, T>(self) -> Cloned<Self>\n    where\n        T: 'a + Clone + Send,\n        Self: ParallelIterator<Item = &'a T>,\n    {\n        Cloned::new(self)\n    }\n\n    /// Creates an iterator which copies all of its elements.  This may be\n    /// useful when you have an iterator over `&T`, but you need `T`, and\n    /// that type implements `Copy`. See also [`cloned()`].\n    ///\n    /// [`cloned()`]: #method.cloned\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [1, 2, 3];\n    ///\n    /// let v_copied: Vec<_> = a.par_iter().copied().collect();\n    ///\n    /// // copied is the same as .map(|&x| x), for integers\n    /// let v_map: Vec<_> = a.par_iter().map(|&x| x).collect();\n    ///\n    /// assert_eq!(v_copied, vec![1, 2, 3]);\n    /// assert_eq!(v_map, vec![1, 2, 3]);\n    /// ```\n    fn copied<'a, T>(self) -> Copied<Self>\n    where\n        T: 'a + Copy + Send,\n        Self: ParallelIterator<Item = &'a T>,\n    {\n        Copied::new(self)\n    }\n\n    /// Applies `inspect_op` to a reference to each item of this iterator,\n    /// producing a new iterator passing through the original items.  This is\n    /// often useful for debugging to see what's happening in iterator stages.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [1, 4, 2, 3];\n    ///\n    /// // this iterator sequence is complex.\n    /// let sum = a.par_iter()\n    ///             .cloned()\n    ///             .filter(|&x| x % 2 == 0)\n    ///             .reduce(|| 0, |sum, i| sum + i);\n    ///\n    /// println!(\"{}\", sum);\n    ///\n    /// // let's add some inspect() calls to investigate what's happening\n    /// let sum = a.par_iter()\n    ///             .cloned()\n    ///             .inspect(|x| println!(\"about to filter: {}\", x))\n    ///             .filter(|&x| x % 2 == 0)\n    ///             .inspect(|x| println!(\"made it through filter: {}\", x))\n    ///             .reduce(|| 0, |sum, i| sum + i);\n    ///\n    /// println!(\"{}\", sum);\n    /// ```\n    fn inspect<OP>(self, inspect_op: OP) -> Inspect<Self, OP>\n    where\n        OP: Fn(&Self::Item) + Sync + Send,\n    {\n        Inspect::new(self, inspect_op)\n    }\n\n    /// Mutates each item of this iterator before yielding it.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let par_iter = (0..5).into_par_iter().update(|x| {*x *= 2;});\n    ///\n    /// let doubles: Vec<_> = par_iter.collect();\n    ///\n    /// assert_eq!(&doubles[..], &[0, 2, 4, 6, 8]);\n    /// ```\n    fn update<F>(self, update_op: F) -> Update<Self, F>\n    where\n        F: Fn(&mut Self::Item) + Sync + Send,\n    {\n        Update::new(self, update_op)\n    }\n\n    /// Applies `filter_op` to each item of this iterator, producing a new\n    /// iterator with only the items that gave `true` results.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let mut par_iter = (0..10).into_par_iter().filter(|x| x % 2 == 0);\n    ///\n    /// let even_numbers: Vec<_> = par_iter.collect();\n    ///\n    /// assert_eq!(&even_numbers[..], &[0, 2, 4, 6, 8]);\n    /// ```\n    fn filter<P>(self, filter_op: P) -> Filter<Self, P>\n    where\n        P: Fn(&Self::Item) -> bool + Sync + Send,\n    {\n        Filter::new(self, filter_op)\n    }\n\n    /// Applies `filter_op` to each item of this iterator to get an `Option`,\n    /// producing a new iterator with only the items from `Some` results.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let mut par_iter = (0..10).into_par_iter()\n    ///                         .filter_map(|x| {\n    ///                             if x % 2 == 0 { Some(x * 3) }\n    ///                             else { None }\n    ///                         });\n    ///\n    /// let even_numbers: Vec<_> = par_iter.collect();\n    ///\n    /// assert_eq!(&even_numbers[..], &[0, 6, 12, 18, 24]);\n    /// ```\n    fn filter_map<P, R>(self, filter_op: P) -> FilterMap<Self, P>\n    where\n        P: Fn(Self::Item) -> Option<R> + Sync + Send,\n        R: Send,\n    {\n        FilterMap::new(self, filter_op)\n    }\n\n    /// Applies `map_op` to each item of this iterator to get nested parallel iterators,\n    /// producing a new parallel iterator that flattens these back into one.\n    ///\n    /// See also [`flat_map_iter`](#method.flat_map_iter).\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [[1, 2], [3, 4], [5, 6], [7, 8]];\n    ///\n    /// let par_iter = a.par_iter().cloned().flat_map(|a| a.to_vec());\n    ///\n    /// let vec: Vec<_> = par_iter.collect();\n    ///\n    /// assert_eq!(&vec[..], &[1, 2, 3, 4, 5, 6, 7, 8]);\n    /// ```\n    fn flat_map<F, PI>(self, map_op: F) -> FlatMap<Self, F>\n    where\n        F: Fn(Self::Item) -> PI + Sync + Send,\n        PI: IntoParallelIterator,\n    {\n        FlatMap::new(self, map_op)\n    }\n\n    /// Applies `map_op` to each item of this iterator to get nested serial iterators,\n    /// producing a new parallel iterator that flattens these back into one.\n    ///\n    /// # `flat_map_iter` versus `flat_map`\n    ///\n    /// These two methods are similar but behave slightly differently. With [`flat_map`],\n    /// each of the nested iterators must be a parallel iterator, and they will be further\n    /// split up with nested parallelism. With `flat_map_iter`, each nested iterator is a\n    /// sequential `Iterator`, and we only parallelize _between_ them, while the items\n    /// produced by each nested iterator are processed sequentially.\n    ///\n    /// When choosing between these methods, consider whether nested parallelism suits the\n    /// potential iterators at hand. If there's little computation involved, or its length\n    /// is much less than the outer parallel iterator, then it may perform better to avoid\n    /// the overhead of parallelism, just flattening sequentially with `flat_map_iter`.\n    /// If there is a lot of computation, potentially outweighing the outer parallel\n    /// iterator, then the nested parallelism of `flat_map` may be worthwhile.\n    ///\n    /// [`flat_map`]: #method.flat_map\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// use std::cell::RefCell;\n    ///\n    /// let a = [[1, 2], [3, 4], [5, 6], [7, 8]];\n    ///\n    /// let par_iter = a.par_iter().flat_map_iter(|a| {\n    ///     // The serial iterator doesn't have to be thread-safe, just its items.\n    ///     let cell_iter = RefCell::new(a.iter().cloned());\n    ///     std::iter::from_fn(move || cell_iter.borrow_mut().next())\n    /// });\n    ///\n    /// let vec: Vec<_> = par_iter.collect();\n    ///\n    /// assert_eq!(&vec[..], &[1, 2, 3, 4, 5, 6, 7, 8]);\n    /// ```\n    fn flat_map_iter<F, SI>(self, map_op: F) -> FlatMapIter<Self, F>\n    where\n        F: Fn(Self::Item) -> SI + Sync + Send,\n        SI: IntoIterator<Item: Send>,\n    {\n        FlatMapIter::new(self, map_op)\n    }\n\n    /// An adaptor that flattens parallel-iterable `Item`s into one large iterator.\n    ///\n    /// See also [`flatten_iter`](#method.flatten_iter).\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let x: Vec<Vec<_>> = vec![vec![1, 2], vec![3, 4]];\n    /// let y: Vec<_> = x.into_par_iter().flatten().collect();\n    ///\n    /// assert_eq!(y, vec![1, 2, 3, 4]);\n    /// ```\n    fn flatten(self) -> Flatten<Self>\n    where\n        Self::Item: IntoParallelIterator,\n    {\n        Flatten::new(self)\n    }\n\n    /// An adaptor that flattens serial-iterable `Item`s into one large iterator.\n    ///\n    /// See also [`flatten`](#method.flatten) and the analogous comparison of\n    /// [`flat_map_iter` versus `flat_map`](#flat_map_iter-versus-flat_map).\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let x: Vec<Vec<_>> = vec![vec![1, 2], vec![3, 4]];\n    /// let iters: Vec<_> = x.into_iter().map(Vec::into_iter).collect();\n    /// let y: Vec<_> = iters.into_par_iter().flatten_iter().collect();\n    ///\n    /// assert_eq!(y, vec![1, 2, 3, 4]);\n    /// ```\n    fn flatten_iter(self) -> FlattenIter<Self>\n    where\n        Self::Item: IntoIterator<Item: Send>,\n    {\n        FlattenIter::new(self)\n    }\n\n    /// Reduces the items in the iterator into one item using `op`.\n    /// The argument `identity` should be a closure that can produce\n    /// \"identity\" value which may be inserted into the sequence as\n    /// needed to create opportunities for parallel execution. So, for\n    /// example, if you are doing a summation, then `identity()` ought\n    /// to produce something that represents the zero for your type\n    /// (but consider just calling `sum()` in that case).\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// // Iterate over a sequence of pairs `(x0, y0), ..., (xN, yN)`\n    /// // and use reduce to compute one pair `(x0 + ... + xN, y0 + ... + yN)`\n    /// // where the first/second elements are summed separately.\n    /// use rayon::prelude::*;\n    /// let sums = [(0, 1), (5, 6), (16, 2), (8, 9)]\n    ///            .par_iter()        // iterating over &(i32, i32)\n    ///            .cloned()          // iterating over (i32, i32)\n    ///            .reduce(|| (0, 0), // the \"identity\" is 0 in both columns\n    ///                    |a, b| (a.0 + b.0, a.1 + b.1));\n    /// assert_eq!(sums, (0 + 5 + 16 + 8, 1 + 6 + 2 + 9));\n    /// ```\n    ///\n    /// **Note:** unlike a sequential `fold` operation, the order in\n    /// which `op` will be applied to reduce the result is not fully\n    /// specified. So `op` should be [associative] or else the results\n    /// will be non-deterministic. And of course `identity()` should\n    /// produce a true identity.\n    ///\n    /// [associative]: https://en.wikipedia.org/wiki/Associative_property\n    fn reduce<OP, ID>(self, identity: ID, op: OP) -> Self::Item\n    where\n        OP: Fn(Self::Item, Self::Item) -> Self::Item + Sync + Send,\n        ID: Fn() -> Self::Item + Sync + Send,\n    {\n        reduce::reduce(self, identity, op)\n    }\n\n    /// Reduces the items in the iterator into one item using `op`.\n    /// If the iterator is empty, `None` is returned; otherwise,\n    /// `Some` is returned.\n    ///\n    /// This version of `reduce` is simple but somewhat less\n    /// efficient. If possible, it is better to call `reduce()`, which\n    /// requires an identity element.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let sums = [(0, 1), (5, 6), (16, 2), (8, 9)]\n    ///            .par_iter()        // iterating over &(i32, i32)\n    ///            .cloned()          // iterating over (i32, i32)\n    ///            .reduce_with(|a, b| (a.0 + b.0, a.1 + b.1))\n    ///            .unwrap();\n    /// assert_eq!(sums, (0 + 5 + 16 + 8, 1 + 6 + 2 + 9));\n    /// ```\n    ///\n    /// **Note:** unlike a sequential `fold` operation, the order in\n    /// which `op` will be applied to reduce the result is not fully\n    /// specified. So `op` should be [associative] or else the results\n    /// will be non-deterministic.\n    ///\n    /// [associative]: https://en.wikipedia.org/wiki/Associative_property\n    fn reduce_with<OP>(self, op: OP) -> Option<Self::Item>\n    where\n        OP: Fn(Self::Item, Self::Item) -> Self::Item + Sync + Send,\n    {\n        fn opt_fold<T>(op: impl Fn(T, T) -> T) -> impl Fn(Option<T>, T) -> Option<T> {\n            move |opt_a, b| match opt_a {\n                Some(a) => Some(op(a, b)),\n                None => Some(b),\n            }\n        }\n\n        fn opt_reduce<T>(op: impl Fn(T, T) -> T) -> impl Fn(Option<T>, Option<T>) -> Option<T> {\n            move |opt_a, opt_b| match (opt_a, opt_b) {\n                (Some(a), Some(b)) => Some(op(a, b)),\n                (Some(v), None) | (None, Some(v)) => Some(v),\n                (None, None) => None,\n            }\n        }\n\n        self.fold(<_>::default, opt_fold(&op))\n            .reduce(<_>::default, opt_reduce(&op))\n    }\n\n    /// Reduces the items in the iterator into one item using a fallible `op`.\n    /// The `identity` argument is used the same way as in [`reduce()`].\n    ///\n    /// [`reduce()`]: #method.reduce\n    ///\n    /// If a `Result::Err` or `Option::None` item is found, or if `op` reduces\n    /// to one, we will attempt to stop processing the rest of the items in the\n    /// iterator as soon as possible, and we will return that terminating value.\n    /// Otherwise, we will return the final reduced `Result::Ok(T)` or\n    /// `Option::Some(T)`.  If there are multiple errors in parallel, it is not\n    /// specified which will be returned.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// // Compute the sum of squares, being careful about overflow.\n    /// fn sum_squares<I: IntoParallelIterator<Item = i32>>(iter: I) -> Option<i32> {\n    ///     iter.into_par_iter()\n    ///         .map(|i| i.checked_mul(i))            // square each item,\n    ///         .try_reduce(|| 0, i32::checked_add)   // and add them up!\n    /// }\n    /// assert_eq!(sum_squares(0..5), Some(0 + 1 + 4 + 9 + 16));\n    ///\n    /// // The sum might overflow\n    /// assert_eq!(sum_squares(0..10_000), None);\n    ///\n    /// // Or the squares might overflow before it even reaches `try_reduce`\n    /// assert_eq!(sum_squares(1_000_000..1_000_001), None);\n    /// ```\n    fn try_reduce<T, OP, ID>(self, identity: ID, op: OP) -> Self::Item\n    where\n        OP: Fn(T, T) -> Self::Item + Sync + Send,\n        ID: Fn() -> T + Sync + Send,\n        Self::Item: Try<Output = T>,\n    {\n        try_reduce::try_reduce(self, identity, op)\n    }\n\n    /// Reduces the items in the iterator into one item using a fallible `op`.\n    ///\n    /// Like [`reduce_with()`], if the iterator is empty, `None` is returned;\n    /// otherwise, `Some` is returned.  Beyond that, it behaves like\n    /// [`try_reduce()`] for handling `Err`/`None`.\n    ///\n    /// [`reduce_with()`]: #method.reduce_with\n    /// [`try_reduce()`]: #method.try_reduce\n    ///\n    /// For instance, with `Option` items, the return value may be:\n    /// - `None`, the iterator was empty\n    /// - `Some(None)`, we stopped after encountering `None`.\n    /// - `Some(Some(x))`, the entire iterator reduced to `x`.\n    ///\n    /// With `Result` items, the nesting is more obvious:\n    /// - `None`, the iterator was empty\n    /// - `Some(Err(e))`, we stopped after encountering an error `e`.\n    /// - `Some(Ok(x))`, the entire iterator reduced to `x`.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let files = [\"/dev/null\", \"/does/not/exist\"];\n    ///\n    /// // Find the biggest file\n    /// files.into_par_iter()\n    ///     .map(|path| std::fs::metadata(path).map(|m| (path, m.len())))\n    ///     .try_reduce_with(|a, b| {\n    ///         Ok(if a.1 >= b.1 { a } else { b })\n    ///     })\n    ///     .expect(\"Some value, since the iterator is not empty\")\n    ///     .expect_err(\"not found\");\n    /// ```\n    fn try_reduce_with<T, OP>(self, op: OP) -> Option<Self::Item>\n    where\n        OP: Fn(T, T) -> Self::Item + Sync + Send,\n        Self::Item: Try<Output = T>,\n    {\n        try_reduce_with::try_reduce_with(self, op)\n    }\n\n    /// Parallel fold is similar to sequential fold except that the\n    /// sequence of items may be subdivided before it is\n    /// folded. Consider a list of numbers like `22 3 77 89 46`. If\n    /// you used sequential fold to add them (`fold(0, |a,b| a+b)`,\n    /// you would wind up first adding 0 + 22, then 22 + 3, then 25 +\n    /// 77, and so forth. The **parallel fold** works similarly except\n    /// that it first breaks up your list into sublists, and hence\n    /// instead of yielding up a single sum at the end, it yields up\n    /// multiple sums. The number of results is nondeterministic, as\n    /// is the point where the breaks occur.\n    ///\n    /// So if we did the same parallel fold (`fold(0, |a,b| a+b)`) on\n    /// our example list, we might wind up with a sequence of two numbers,\n    /// like so:\n    ///\n    /// ```notrust\n    /// 22 3 77 89 46\n    ///       |     |\n    ///     102   135\n    /// ```\n    ///\n    /// Or perhaps these three numbers:\n    ///\n    /// ```notrust\n    /// 22 3 77 89 46\n    ///       |  |  |\n    ///     102 89 46\n    /// ```\n    ///\n    /// In general, Rayon will attempt to find good breaking points\n    /// that keep all of your cores busy.\n    ///\n    /// ### Fold versus reduce\n    ///\n    /// The `fold()` and `reduce()` methods each take an identity element\n    /// and a combining function, but they operate rather differently.\n    ///\n    /// `reduce()` requires that the identity function has the same\n    /// type as the things you are iterating over, and it fully\n    /// reduces the list of items into a single item. So, for example,\n    /// imagine we are iterating over a list of bytes `bytes: [128_u8,\n    /// 64_u8, 64_u8]`. If we used `bytes.reduce(|| 0_u8, |a: u8, b:\n    /// u8| a + b)`, we would get an overflow. This is because `0`,\n    /// `a`, and `b` here are all bytes, just like the numbers in the\n    /// list (I wrote the types explicitly above, but those are the\n    /// only types you can use). To avoid the overflow, we would need\n    /// to do something like `bytes.map(|b| b as u32).reduce(|| 0, |a,\n    /// b| a + b)`, in which case our result would be `256`.\n    ///\n    /// In contrast, with `fold()`, the identity function does not\n    /// have to have the same type as the things you are iterating\n    /// over, and you potentially get back many results. So, if we\n    /// continue with the `bytes` example from the previous paragraph,\n    /// we could do `bytes.fold(|| 0_u32, |a, b| a + (b as u32))` to\n    /// convert our bytes into `u32`. And of course we might not get\n    /// back a single sum.\n    ///\n    /// There is a more subtle distinction as well, though it's\n    /// actually implied by the above points. When you use `reduce()`,\n    /// your reduction function is sometimes called with values that\n    /// were never part of your original parallel iterator (for\n    /// example, both the left and right might be a partial sum). With\n    /// `fold()`, in contrast, the left value in the fold function is\n    /// always the accumulator, and the right value is always from\n    /// your original sequence.\n    ///\n    /// ### Fold vs Map/Reduce\n    ///\n    /// Fold makes sense if you have some operation where it is\n    /// cheaper to create groups of elements at a time. For example,\n    /// imagine collecting characters into a string. If you were going\n    /// to use map/reduce, you might try this:\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let s =\n    ///     ['a', 'b', 'c', 'd', 'e']\n    ///     .par_iter()\n    ///     .map(|c: &char| format!(\"{}\", c))\n    ///     .reduce(|| String::new(),\n    ///             |mut a: String, b: String| { a.push_str(&b); a });\n    ///\n    /// assert_eq!(s, \"abcde\");\n    /// ```\n    ///\n    /// Because reduce produces the same type of element as its input,\n    /// you have to first map each character into a string, and then\n    /// you can reduce them. This means we create one string per\n    /// element in our iterator -- not so great. Using `fold`, we can\n    /// do this instead:\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let s =\n    ///     ['a', 'b', 'c', 'd', 'e']\n    ///     .par_iter()\n    ///     .fold(|| String::new(),\n    ///             |mut s: String, c: &char| { s.push(*c); s })\n    ///     .reduce(|| String::new(),\n    ///             |mut a: String, b: String| { a.push_str(&b); a });\n    ///\n    /// assert_eq!(s, \"abcde\");\n    /// ```\n    ///\n    /// Now `fold` will process groups of our characters at a time,\n    /// and we only make one string per group. We should wind up with\n    /// some small-ish number of strings roughly proportional to the\n    /// number of CPUs you have (it will ultimately depend on how busy\n    /// your processors are). Note that we still need to do a reduce\n    /// afterwards to combine those groups of strings into a single\n    /// string.\n    ///\n    /// You could use a similar trick to save partial results (e.g., a\n    /// cache) or something similar.\n    ///\n    /// ### Combining fold with other operations\n    ///\n    /// You can combine `fold` with `reduce` if you want to produce a\n    /// single value. This is then roughly equivalent to a map/reduce\n    /// combination in effect:\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let bytes = 0..22_u8;\n    /// let sum = bytes.into_par_iter()\n    ///                .fold(|| 0_u32, |a: u32, b: u8| a + (b as u32))\n    ///                .sum::<u32>();\n    ///\n    /// assert_eq!(sum, (0..22).sum()); // compare to sequential\n    /// ```\n    fn fold<T, ID, F>(self, identity: ID, fold_op: F) -> Fold<Self, ID, F>\n    where\n        F: Fn(T, Self::Item) -> T + Sync + Send,\n        ID: Fn() -> T + Sync + Send,\n        T: Send,\n    {\n        Fold::new(self, identity, fold_op)\n    }\n\n    /// Applies `fold_op` to the given `init` value with each item of this\n    /// iterator, finally producing the value for further use.\n    ///\n    /// This works essentially like `fold(|| init.clone(), fold_op)`, except\n    /// it doesn't require the `init` type to be `Sync`, nor any other form\n    /// of added synchronization.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let bytes = 0..22_u8;\n    /// let sum = bytes.into_par_iter()\n    ///                .fold_with(0_u32, |a: u32, b: u8| a + (b as u32))\n    ///                .sum::<u32>();\n    ///\n    /// assert_eq!(sum, (0..22).sum()); // compare to sequential\n    /// ```\n    fn fold_with<F, T>(self, init: T, fold_op: F) -> FoldWith<Self, T, F>\n    where\n        F: Fn(T, Self::Item) -> T + Sync + Send,\n        T: Send + Clone,\n    {\n        FoldWith::new(self, init, fold_op)\n    }\n\n    /// Performs a fallible parallel fold.\n    ///\n    /// This is a variation of [`fold()`] for operations which can fail with\n    /// `Option::None` or `Result::Err`.  The first such failure stops\n    /// processing the local set of items, without affecting other folds in the\n    /// iterator's subdivisions.\n    ///\n    /// Often, `try_fold()` will be followed by [`try_reduce()`]\n    /// for a final reduction and global short-circuiting effect.\n    ///\n    /// [`fold()`]: #method.fold\n    /// [`try_reduce()`]: #method.try_reduce\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let bytes = 0..22_u8;\n    /// let sum = bytes.into_par_iter()\n    ///                .try_fold(|| 0_u32, |a: u32, b: u8| a.checked_add(b as u32))\n    ///                .try_reduce(|| 0, u32::checked_add);\n    ///\n    /// assert_eq!(sum, Some((0..22).sum())); // compare to sequential\n    /// ```\n    fn try_fold<T, R, ID, F>(self, identity: ID, fold_op: F) -> TryFold<Self, R, ID, F>\n    where\n        F: Fn(T, Self::Item) -> R + Sync + Send,\n        ID: Fn() -> T + Sync + Send,\n        R: Try<Output = T> + Send,\n    {\n        TryFold::new(self, identity, fold_op)\n    }\n\n    /// Performs a fallible parallel fold with a cloneable `init` value.\n    ///\n    /// This combines the `init` semantics of [`fold_with()`] and the failure\n    /// semantics of [`try_fold()`].\n    ///\n    /// [`fold_with()`]: #method.fold_with\n    /// [`try_fold()`]: #method.try_fold\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let bytes = 0..22_u8;\n    /// let sum = bytes.into_par_iter()\n    ///                .try_fold_with(0_u32, |a: u32, b: u8| a.checked_add(b as u32))\n    ///                .try_reduce(|| 0, u32::checked_add);\n    ///\n    /// assert_eq!(sum, Some((0..22).sum())); // compare to sequential\n    /// ```\n    fn try_fold_with<F, T, R>(self, init: T, fold_op: F) -> TryFoldWith<Self, R, F>\n    where\n        F: Fn(T, Self::Item) -> R + Sync + Send,\n        R: Try<Output = T> + Send,\n        T: Clone + Send,\n    {\n        TryFoldWith::new(self, init, fold_op)\n    }\n\n    /// Sums up the items in the iterator.\n    ///\n    /// Note that the order in items will be reduced is not specified,\n    /// so if the `+` operator is not truly [associative] \\(as is the\n    /// case for floating point numbers), then the results are not\n    /// fully deterministic.\n    ///\n    /// [associative]: https://en.wikipedia.org/wiki/Associative_property\n    ///\n    /// Basically equivalent to `self.reduce(|| 0, |a, b| a + b)`,\n    /// except that the type of `0` and the `+` operation may vary\n    /// depending on the type of value being produced.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [1, 5, 7];\n    ///\n    /// let sum: i32 = a.par_iter().sum();\n    ///\n    /// assert_eq!(sum, 13);\n    /// ```\n    fn sum<S>(self) -> S\n    where\n        S: Send + Sum<Self::Item> + Sum<S>,\n    {\n        sum::sum(self)\n    }\n\n    /// Multiplies all the items in the iterator.\n    ///\n    /// Note that the order in items will be reduced is not specified,\n    /// so if the `*` operator is not truly [associative] \\(as is the\n    /// case for floating point numbers), then the results are not\n    /// fully deterministic.\n    ///\n    /// [associative]: https://en.wikipedia.org/wiki/Associative_property\n    ///\n    /// Basically equivalent to `self.reduce(|| 1, |a, b| a * b)`,\n    /// except that the type of `1` and the `*` operation may vary\n    /// depending on the type of value being produced.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// fn factorial(n: u32) -> u32 {\n    ///    (1..n+1).into_par_iter().product()\n    /// }\n    ///\n    /// assert_eq!(factorial(0), 1);\n    /// assert_eq!(factorial(1), 1);\n    /// assert_eq!(factorial(5), 120);\n    /// ```\n    fn product<P>(self) -> P\n    where\n        P: Send + Product<Self::Item> + Product<P>,\n    {\n        product::product(self)\n    }\n\n    /// Computes the minimum of all the items in the iterator. If the\n    /// iterator is empty, `None` is returned; otherwise, `Some(min)`\n    /// is returned.\n    ///\n    /// Note that the order in which the items will be reduced is not\n    /// specified, so if the `Ord` impl is not truly associative, then\n    /// the results are not deterministic.\n    ///\n    /// Basically equivalent to `self.reduce_with(|a, b| Ord::min(a, b))`.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [45, 74, 32];\n    ///\n    /// assert_eq!(a.par_iter().min(), Some(&32));\n    ///\n    /// let b: [i32; 0] = [];\n    ///\n    /// assert_eq!(b.par_iter().min(), None);\n    /// ```\n    fn min(self) -> Option<Self::Item>\n    where\n        Self::Item: Ord,\n    {\n        self.reduce_with(Ord::min)\n    }\n\n    /// Computes the minimum of all the items in the iterator with respect to\n    /// the given comparison function. If the iterator is empty, `None` is\n    /// returned; otherwise, `Some(min)` is returned.\n    ///\n    /// Note that the order in which the items will be reduced is not\n    /// specified, so if the comparison function is not associative, then\n    /// the results are not deterministic.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [-3_i32, 77, 53, 240, -1];\n    ///\n    /// assert_eq!(a.par_iter().min_by(|x, y| x.cmp(y)), Some(&-3));\n    /// ```\n    fn min_by<F>(self, f: F) -> Option<Self::Item>\n    where\n        F: Sync + Send + Fn(&Self::Item, &Self::Item) -> Ordering,\n    {\n        fn min<T>(f: impl Fn(&T, &T) -> Ordering) -> impl Fn(T, T) -> T {\n            move |a, b| match f(&a, &b) {\n                Ordering::Greater => b,\n                _ => a,\n            }\n        }\n\n        self.reduce_with(min(f))\n    }\n\n    /// Computes the item that yields the minimum value for the given\n    /// function. If the iterator is empty, `None` is returned;\n    /// otherwise, `Some(item)` is returned.\n    ///\n    /// Note that the order in which the items will be reduced is not\n    /// specified, so if the `Ord` impl is not truly associative, then\n    /// the results are not deterministic.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [-3_i32, 34, 2, 5, -10, -3, -23];\n    ///\n    /// assert_eq!(a.par_iter().min_by_key(|x| x.abs()), Some(&2));\n    /// ```\n    fn min_by_key<K, F>(self, f: F) -> Option<Self::Item>\n    where\n        K: Ord + Send,\n        F: Sync + Send + Fn(&Self::Item) -> K,\n    {\n        fn key<T, K>(f: impl Fn(&T) -> K) -> impl Fn(T) -> (K, T) {\n            move |x| (f(&x), x)\n        }\n\n        fn min_key<T, K: Ord>(a: (K, T), b: (K, T)) -> (K, T) {\n            match (a.0).cmp(&b.0) {\n                Ordering::Greater => b,\n                _ => a,\n            }\n        }\n\n        let (_, x) = self.map(key(f)).reduce_with(min_key)?;\n        Some(x)\n    }\n\n    /// Computes the maximum of all the items in the iterator. If the\n    /// iterator is empty, `None` is returned; otherwise, `Some(max)`\n    /// is returned.\n    ///\n    /// Note that the order in which the items will be reduced is not\n    /// specified, so if the `Ord` impl is not truly associative, then\n    /// the results are not deterministic.\n    ///\n    /// Basically equivalent to `self.reduce_with(|a, b| Ord::max(a, b))`.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [45, 74, 32];\n    ///\n    /// assert_eq!(a.par_iter().max(), Some(&74));\n    ///\n    /// let b: [i32; 0] = [];\n    ///\n    /// assert_eq!(b.par_iter().max(), None);\n    /// ```\n    fn max(self) -> Option<Self::Item>\n    where\n        Self::Item: Ord,\n    {\n        self.reduce_with(Ord::max)\n    }\n\n    /// Computes the maximum of all the items in the iterator with respect to\n    /// the given comparison function. If the iterator is empty, `None` is\n    /// returned; otherwise, `Some(max)` is returned.\n    ///\n    /// Note that the order in which the items will be reduced is not\n    /// specified, so if the comparison function is not associative, then\n    /// the results are not deterministic.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [-3_i32, 77, 53, 240, -1];\n    ///\n    /// assert_eq!(a.par_iter().max_by(|x, y| x.abs().cmp(&y.abs())), Some(&240));\n    /// ```\n    fn max_by<F>(self, f: F) -> Option<Self::Item>\n    where\n        F: Sync + Send + Fn(&Self::Item, &Self::Item) -> Ordering,\n    {\n        fn max<T>(f: impl Fn(&T, &T) -> Ordering) -> impl Fn(T, T) -> T {\n            move |a, b| match f(&a, &b) {\n                Ordering::Greater => a,\n                _ => b,\n            }\n        }\n\n        self.reduce_with(max(f))\n    }\n\n    /// Computes the item that yields the maximum value for the given\n    /// function. If the iterator is empty, `None` is returned;\n    /// otherwise, `Some(item)` is returned.\n    ///\n    /// Note that the order in which the items will be reduced is not\n    /// specified, so if the `Ord` impl is not truly associative, then\n    /// the results are not deterministic.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [-3_i32, 34, 2, 5, -10, -3, -23];\n    ///\n    /// assert_eq!(a.par_iter().max_by_key(|x| x.abs()), Some(&34));\n    /// ```\n    fn max_by_key<K, F>(self, f: F) -> Option<Self::Item>\n    where\n        K: Ord + Send,\n        F: Sync + Send + Fn(&Self::Item) -> K,\n    {\n        fn key<T, K>(f: impl Fn(&T) -> K) -> impl Fn(T) -> (K, T) {\n            move |x| (f(&x), x)\n        }\n\n        fn max_key<T, K: Ord>(a: (K, T), b: (K, T)) -> (K, T) {\n            match (a.0).cmp(&b.0) {\n                Ordering::Greater => a,\n                _ => b,\n            }\n        }\n\n        let (_, x) = self.map(key(f)).reduce_with(max_key)?;\n        Some(x)\n    }\n\n    /// Takes two iterators and creates a new iterator over both.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [0, 1, 2];\n    /// let b = [9, 8, 7];\n    ///\n    /// let par_iter = a.par_iter().chain(b.par_iter());\n    ///\n    /// let chained: Vec<_> = par_iter.cloned().collect();\n    ///\n    /// assert_eq!(&chained[..], &[0, 1, 2, 9, 8, 7]);\n    /// ```\n    fn chain<C>(self, chain: C) -> Chain<Self, C::Iter>\n    where\n        C: IntoParallelIterator<Item = Self::Item>,\n    {\n        Chain::new(self, chain.into_par_iter())\n    }\n\n    /// Searches for **some** item in the parallel iterator that\n    /// matches the given predicate and returns it. This operation\n    /// is similar to [`find` on sequential iterators][find] but\n    /// the item returned may not be the **first** one in the parallel\n    /// sequence which matches, since we search the entire sequence in parallel.\n    ///\n    /// Once a match is found, we will attempt to stop processing\n    /// the rest of the items in the iterator as soon as possible\n    /// (just as `find` stops iterating once a match is found).\n    ///\n    /// [find]: Iterator::find()\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [1, 2, 3, 3];\n    ///\n    /// assert_eq!(a.par_iter().find_any(|&&x| x == 3), Some(&3));\n    ///\n    /// assert_eq!(a.par_iter().find_any(|&&x| x == 100), None);\n    /// ```\n    fn find_any<P>(self, predicate: P) -> Option<Self::Item>\n    where\n        P: Fn(&Self::Item) -> bool + Sync + Send,\n    {\n        find::find(self, predicate)\n    }\n\n    /// Searches for the sequentially **first** item in the parallel iterator\n    /// that matches the given predicate and returns it.\n    ///\n    /// Once a match is found, all attempts to the right of the match\n    /// will be stopped, while attempts to the left must continue in case\n    /// an earlier match is found.\n    ///\n    /// For added performance, you might consider using `find_first` in conjunction with\n    /// [`by_exponential_blocks()`][IndexedParallelIterator::by_exponential_blocks].\n    ///\n    /// Note that not all parallel iterators have a useful order, much like\n    /// sequential `HashMap` iteration, so \"first\" may be nebulous.  If you\n    /// just want the first match that discovered anywhere in the iterator,\n    /// `find_any` is a better choice.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [1, 2, 3, 3];\n    ///\n    /// assert_eq!(a.par_iter().find_first(|&&x| x == 3), Some(&3));\n    ///\n    /// assert_eq!(a.par_iter().find_first(|&&x| x == 100), None);\n    /// ```\n    fn find_first<P>(self, predicate: P) -> Option<Self::Item>\n    where\n        P: Fn(&Self::Item) -> bool + Sync + Send,\n    {\n        find_first_last::find_first(self, predicate)\n    }\n\n    /// Searches for the sequentially **last** item in the parallel iterator\n    /// that matches the given predicate and returns it.\n    ///\n    /// Once a match is found, all attempts to the left of the match\n    /// will be stopped, while attempts to the right must continue in case\n    /// a later match is found.\n    ///\n    /// Note that not all parallel iterators have a useful order, much like\n    /// sequential `HashMap` iteration, so \"last\" may be nebulous.  When the\n    /// order doesn't actually matter to you, `find_any` is a better choice.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [1, 2, 3, 3];\n    ///\n    /// assert_eq!(a.par_iter().find_last(|&&x| x == 3), Some(&3));\n    ///\n    /// assert_eq!(a.par_iter().find_last(|&&x| x == 100), None);\n    /// ```\n    fn find_last<P>(self, predicate: P) -> Option<Self::Item>\n    where\n        P: Fn(&Self::Item) -> bool + Sync + Send,\n    {\n        find_first_last::find_last(self, predicate)\n    }\n\n    /// Applies the given predicate to the items in the parallel iterator\n    /// and returns **any** non-None result of the map operation.\n    ///\n    /// Once a non-None value is produced from the map operation, we will\n    /// attempt to stop processing the rest of the items in the iterator\n    /// as soon as possible.\n    ///\n    /// Note that this method only returns **some** item in the parallel\n    /// iterator that is not None from the map predicate. The item returned\n    /// may not be the **first** non-None value produced in the parallel\n    /// sequence, since the entire sequence is mapped over in parallel.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let c = [\"lol\", \"NaN\", \"5\", \"5\"];\n    ///\n    /// let found_number = c.par_iter().find_map_any(|s| s.parse().ok());\n    ///\n    /// assert_eq!(found_number, Some(5));\n    /// ```\n    fn find_map_any<P, R>(self, predicate: P) -> Option<R>\n    where\n        P: Fn(Self::Item) -> Option<R> + Sync + Send,\n        R: Send,\n    {\n        fn yes<T>(_: &T) -> bool {\n            true\n        }\n        self.filter_map(predicate).find_any(yes)\n    }\n\n    /// Applies the given predicate to the items in the parallel iterator and\n    /// returns the sequentially **first** non-None result of the map operation.\n    ///\n    /// Once a non-None value is produced from the map operation, all attempts\n    /// to the right of the match will be stopped, while attempts to the left\n    /// must continue in case an earlier match is found.\n    ///\n    /// Note that not all parallel iterators have a useful order, much like\n    /// sequential `HashMap` iteration, so \"first\" may be nebulous. If you\n    /// just want the first non-None value discovered anywhere in the iterator,\n    /// `find_map_any` is a better choice.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let c = [\"lol\", \"NaN\", \"2\", \"5\"];\n    ///\n    /// let first_number = c.par_iter().find_map_first(|s| s.parse().ok());\n    ///\n    /// assert_eq!(first_number, Some(2));\n    /// ```\n    fn find_map_first<P, R>(self, predicate: P) -> Option<R>\n    where\n        P: Fn(Self::Item) -> Option<R> + Sync + Send,\n        R: Send,\n    {\n        fn yes<T>(_: &T) -> bool {\n            true\n        }\n        self.filter_map(predicate).find_first(yes)\n    }\n\n    /// Applies the given predicate to the items in the parallel iterator and\n    /// returns the sequentially **last** non-None result of the map operation.\n    ///\n    /// Once a non-None value is produced from the map operation, all attempts\n    /// to the left of the match will be stopped, while attempts to the right\n    /// must continue in case a later match is found.\n    ///\n    /// Note that not all parallel iterators have a useful order, much like\n    /// sequential `HashMap` iteration, so \"first\" may be nebulous. If you\n    /// just want the first non-None value discovered anywhere in the iterator,\n    /// `find_map_any` is a better choice.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let c = [\"lol\", \"NaN\", \"2\", \"5\"];\n    ///\n    /// let last_number = c.par_iter().find_map_last(|s| s.parse().ok());\n    ///\n    /// assert_eq!(last_number, Some(5));\n    /// ```\n    fn find_map_last<P, R>(self, predicate: P) -> Option<R>\n    where\n        P: Fn(Self::Item) -> Option<R> + Sync + Send,\n        R: Send,\n    {\n        fn yes<T>(_: &T) -> bool {\n            true\n        }\n        self.filter_map(predicate).find_last(yes)\n    }\n\n    #[doc(hidden)]\n    #[deprecated(note = \"parallel `find` does not search in order -- use `find_any`, \\\\\n                         `find_first`, or `find_last`\")]\n    fn find<P>(self, predicate: P) -> Option<Self::Item>\n    where\n        P: Fn(&Self::Item) -> bool + Sync + Send,\n    {\n        self.find_any(predicate)\n    }\n\n    /// Searches for **some** item in the parallel iterator that\n    /// matches the given predicate, and if so returns true.  Once\n    /// a match is found, we'll attempt to stop process the rest\n    /// of the items.  Proving that there's no match, returning false,\n    /// does require visiting every item.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [0, 12, 3, 4, 0, 23, 0];\n    ///\n    /// let is_valid = a.par_iter().any(|&x| x > 10);\n    ///\n    /// assert!(is_valid);\n    /// ```\n    fn any<P>(self, predicate: P) -> bool\n    where\n        P: Fn(Self::Item) -> bool + Sync + Send,\n    {\n        self.map(predicate).find_any(bool::clone).is_some()\n    }\n\n    /// Tests that every item in the parallel iterator matches the given\n    /// predicate, and if so returns true.  If a counter-example is found,\n    /// we'll attempt to stop processing more items, then return false.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [0, 12, 3, 4, 0, 23, 0];\n    ///\n    /// let is_valid = a.par_iter().all(|&x| x > 10);\n    ///\n    /// assert!(!is_valid);\n    /// ```\n    fn all<P>(self, predicate: P) -> bool\n    where\n        P: Fn(Self::Item) -> bool + Sync + Send,\n    {\n        #[inline]\n        fn is_false(x: &bool) -> bool {\n            !x\n        }\n\n        self.map(predicate).find_any(is_false).is_none()\n    }\n\n    /// Creates an iterator over the `Some` items of this iterator, halting\n    /// as soon as any `None` is found.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// use std::sync::atomic::{AtomicUsize, Ordering};\n    ///\n    /// let counter = AtomicUsize::new(0);\n    /// let value = (0_i32..2048)\n    ///     .into_par_iter()\n    ///     .map(|x| {\n    ///              counter.fetch_add(1, Ordering::SeqCst);\n    ///              if x < 1024 { Some(x) } else { None }\n    ///          })\n    ///     .while_some()\n    ///     .max();\n    ///\n    /// assert!(value < Some(1024));\n    /// assert!(counter.load(Ordering::SeqCst) < 2048); // should not have visited every single one\n    /// ```\n    fn while_some<T>(self) -> WhileSome<Self>\n    where\n        Self: ParallelIterator<Item = Option<T>>,\n        T: Send,\n    {\n        WhileSome::new(self)\n    }\n\n    /// Wraps an iterator with a fuse in case of panics, to halt all threads\n    /// as soon as possible.\n    ///\n    /// Panics within parallel iterators are always propagated to the caller,\n    /// but they don't always halt the rest of the iterator right away, due to\n    /// the internal semantics of [`join`]. This adaptor makes a greater effort\n    /// to stop processing other items sooner, with the cost of additional\n    /// synchronization overhead, which may also inhibit some optimizations.\n    ///\n    /// [`join`]: crate::join()#panics\n    ///\n    /// # Examples\n    ///\n    /// If this code didn't use `panic_fuse()`, it would continue processing\n    /// many more items in other threads (with long sleep delays) before the\n    /// panic is finally propagated.\n    ///\n    /// ```should_panic\n    /// use rayon::prelude::*;\n    /// use std::{thread, time};\n    ///\n    /// (0..1_000_000)\n    ///     .into_par_iter()\n    ///     .panic_fuse()\n    ///     .for_each(|i| {\n    ///         // simulate some work\n    ///         thread::sleep(time::Duration::from_secs(1));\n    ///         assert!(i > 0); // oops!\n    ///     });\n    /// ```\n    fn panic_fuse(self) -> PanicFuse<Self> {\n        PanicFuse::new(self)\n    }\n\n    /// Creates a fresh collection containing all the elements produced\n    /// by this parallel iterator.\n    ///\n    /// You may prefer [`collect_into_vec()`] implemented on\n    /// [`IndexedParallelIterator`], if your underlying iterator also implements\n    /// it. [`collect_into_vec()`] allocates efficiently with precise knowledge\n    /// of how many elements the iterator contains, and even allows you to reuse\n    /// an existing vector's backing store rather than allocating a fresh vector.\n    ///\n    /// See also [`collect_vec_list()`] for collecting into a\n    /// `LinkedList<Vec<T>>`.\n    ///\n    /// [`collect_into_vec()`]: IndexedParallelIterator::collect_into_vec()\n    /// [`collect_vec_list()`]: Self::collect_vec_list()\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let sync_vec: Vec<_> = (0..100).into_iter().collect();\n    ///\n    /// let async_vec: Vec<_> = (0..100).into_par_iter().collect();\n    ///\n    /// assert_eq!(sync_vec, async_vec);\n    /// ```\n    ///\n    /// You can collect a pair of collections like [`unzip`](#method.unzip)\n    /// for paired items:\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [(0, 1), (1, 2), (2, 3), (3, 4)];\n    /// let (first, second): (Vec<_>, Vec<_>) = a.into_par_iter().collect();\n    ///\n    /// assert_eq!(first, [0, 1, 2, 3]);\n    /// assert_eq!(second, [1, 2, 3, 4]);\n    /// ```\n    ///\n    /// Or like [`partition_map`](#method.partition_map) for `Either` items:\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// use rayon::iter::Either;\n    ///\n    /// let (left, right): (Vec<_>, Vec<_>) = (0..8).into_par_iter().map(|x| {\n    ///     if x % 2 == 0 {\n    ///         Either::Left(x * 4)\n    ///     } else {\n    ///         Either::Right(x * 3)\n    ///     }\n    /// }).collect();\n    ///\n    /// assert_eq!(left, [0, 8, 16, 24]);\n    /// assert_eq!(right, [3, 9, 15, 21]);\n    /// ```\n    ///\n    /// You can even collect an arbitrarily-nested combination of pairs and `Either`:\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// use rayon::iter::Either;\n    ///\n    /// let (first, (left, right)): (Vec<_>, (Vec<_>, Vec<_>))\n    ///     = (0..8).into_par_iter().map(|x| {\n    ///         if x % 2 == 0 {\n    ///             (x, Either::Left(x * 4))\n    ///         } else {\n    ///             (-x, Either::Right(x * 3))\n    ///         }\n    ///     }).collect();\n    ///\n    /// assert_eq!(first, [0, -1, 2, -3, 4, -5, 6, -7]);\n    /// assert_eq!(left, [0, 8, 16, 24]);\n    /// assert_eq!(right, [3, 9, 15, 21]);\n    /// ```\n    ///\n    /// All of that can _also_ be combined with short-circuiting collection of\n    /// `Result` or `Option` types:\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// use rayon::iter::Either;\n    ///\n    /// let result: Result<(Vec<_>, (Vec<_>, Vec<_>)), _>\n    ///     = (0..8).into_par_iter().map(|x| {\n    ///         if x > 5 {\n    ///             Err(x)\n    ///         } else if x % 2 == 0 {\n    ///             Ok((x, Either::Left(x * 4)))\n    ///         } else {\n    ///             Ok((-x, Either::Right(x * 3)))\n    ///         }\n    ///     }).collect();\n    ///\n    /// let error = result.unwrap_err();\n    /// assert!(error == 6 || error == 7);\n    /// ```\n    fn collect<C>(self) -> C\n    where\n        C: FromParallelIterator<Self::Item>,\n    {\n        C::from_par_iter(self)\n    }\n\n    /// Unzips the items of a parallel iterator into a pair of arbitrary\n    /// `ParallelExtend` containers.\n    ///\n    /// You may prefer to use `unzip_into_vecs()`, which allocates more\n    /// efficiently with precise knowledge of how many elements the\n    /// iterator contains, and even allows you to reuse existing\n    /// vectors' backing stores rather than allocating fresh vectors.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [(0, 1), (1, 2), (2, 3), (3, 4)];\n    ///\n    /// let (left, right): (Vec<_>, Vec<_>) = a.par_iter().cloned().unzip();\n    ///\n    /// assert_eq!(left, [0, 1, 2, 3]);\n    /// assert_eq!(right, [1, 2, 3, 4]);\n    /// ```\n    ///\n    /// Nested pairs can be unzipped too.\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let (values, (squares, cubes)): (Vec<_>, (Vec<_>, Vec<_>)) = (0..4).into_par_iter()\n    ///     .map(|i| (i, (i * i, i * i * i)))\n    ///     .unzip();\n    ///\n    /// assert_eq!(values, [0, 1, 2, 3]);\n    /// assert_eq!(squares, [0, 1, 4, 9]);\n    /// assert_eq!(cubes, [0, 1, 8, 27]);\n    /// ```\n    fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)\n    where\n        Self: ParallelIterator<Item = (A, B)>,\n        FromA: Default + Send + ParallelExtend<A>,\n        FromB: Default + Send + ParallelExtend<B>,\n        A: Send,\n        B: Send,\n    {\n        unzip::unzip(self)\n    }\n\n    /// Partitions the items of a parallel iterator into a pair of arbitrary\n    /// `ParallelExtend` containers.  Items for which the `predicate` returns\n    /// true go into the first container, and the rest go into the second.\n    ///\n    /// Note: unlike the standard `Iterator::partition`, this allows distinct\n    /// collection types for the left and right items.  This is more flexible,\n    /// but may require new type annotations when converting sequential code\n    /// that used type inference assuming the two were the same.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let (left, right): (Vec<_>, Vec<_>) = (0..8).into_par_iter().partition(|x| x % 2 == 0);\n    ///\n    /// assert_eq!(left, [0, 2, 4, 6]);\n    /// assert_eq!(right, [1, 3, 5, 7]);\n    /// ```\n    fn partition<A, B, P>(self, predicate: P) -> (A, B)\n    where\n        A: Default + Send + ParallelExtend<Self::Item>,\n        B: Default + Send + ParallelExtend<Self::Item>,\n        P: Fn(&Self::Item) -> bool + Sync + Send,\n    {\n        unzip::partition(self, predicate)\n    }\n\n    /// Partitions and maps the items of a parallel iterator into a pair of\n    /// arbitrary `ParallelExtend` containers.  `Either::Left` items go into\n    /// the first container, and `Either::Right` items go into the second.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// use rayon::iter::Either;\n    ///\n    /// let (left, right): (Vec<_>, Vec<_>) = (0..8).into_par_iter()\n    ///     .partition_map(|x| {\n    ///         if x % 2 == 0 {\n    ///             Either::Left(x * 4)\n    ///         } else {\n    ///             Either::Right(x * 3)\n    ///         }\n    ///     });\n    ///\n    /// assert_eq!(left, [0, 8, 16, 24]);\n    /// assert_eq!(right, [3, 9, 15, 21]);\n    /// ```\n    ///\n    /// Nested `Either` enums can be split as well.\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// use rayon::iter::Either::*;\n    ///\n    /// let ((fizzbuzz, fizz), (buzz, other)): ((Vec<_>, Vec<_>), (Vec<_>, Vec<_>)) = (1..20)\n    ///     .into_par_iter()\n    ///     .partition_map(|x| match (x % 3, x % 5) {\n    ///         (0, 0) => Left(Left(x)),\n    ///         (0, _) => Left(Right(x)),\n    ///         (_, 0) => Right(Left(x)),\n    ///         (_, _) => Right(Right(x)),\n    ///     });\n    ///\n    /// assert_eq!(fizzbuzz, [15]);\n    /// assert_eq!(fizz, [3, 6, 9, 12, 18]);\n    /// assert_eq!(buzz, [5, 10]);\n    /// assert_eq!(other, [1, 2, 4, 7, 8, 11, 13, 14, 16, 17, 19]);\n    /// ```\n    fn partition_map<A, B, P, L, R>(self, predicate: P) -> (A, B)\n    where\n        A: Default + Send + ParallelExtend<L>,\n        B: Default + Send + ParallelExtend<R>,\n        P: Fn(Self::Item) -> Either<L, R> + Sync + Send,\n        L: Send,\n        R: Send,\n    {\n        unzip::partition_map(self, predicate)\n    }\n\n    /// Intersperses clones of an element between items of this iterator.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let x = vec![1, 2, 3];\n    /// let r: Vec<_> = x.into_par_iter().intersperse(-1).collect();\n    ///\n    /// assert_eq!(r, vec![1, -1, 2, -1, 3]);\n    /// ```\n    fn intersperse(self, element: Self::Item) -> Intersperse<Self>\n    where\n        Self::Item: Clone,\n    {\n        Intersperse::new(self, element)\n    }\n\n    /// Creates an iterator that yields `n` elements from *anywhere* in the original iterator.\n    ///\n    /// This is similar to [`IndexedParallelIterator::take`] without being\n    /// constrained to the \"first\" `n` of the original iterator order. The\n    /// taken items will still maintain their relative order where that is\n    /// visible in `collect`, `reduce`, and similar outputs.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let result: Vec<_> = (0..100)\n    ///     .into_par_iter()\n    ///     .filter(|&x| x % 2 == 0)\n    ///     .take_any(5)\n    ///     .collect();\n    ///\n    /// assert_eq!(result.len(), 5);\n    /// assert!(result.windows(2).all(|w| w[0] < w[1]));\n    /// ```\n    fn take_any(self, n: usize) -> TakeAny<Self> {\n        TakeAny::new(self, n)\n    }\n\n    /// Creates an iterator that skips `n` elements from *anywhere* in the original iterator.\n    ///\n    /// This is similar to [`IndexedParallelIterator::skip`] without being\n    /// constrained to the \"first\" `n` of the original iterator order. The\n    /// remaining items will still maintain their relative order where that is\n    /// visible in `collect`, `reduce`, and similar outputs.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let result: Vec<_> = (0..100)\n    ///     .into_par_iter()\n    ///     .filter(|&x| x % 2 == 0)\n    ///     .skip_any(5)\n    ///     .collect();\n    ///\n    /// assert_eq!(result.len(), 45);\n    /// assert!(result.windows(2).all(|w| w[0] < w[1]));\n    /// ```\n    fn skip_any(self, n: usize) -> SkipAny<Self> {\n        SkipAny::new(self, n)\n    }\n\n    /// Creates an iterator that takes elements from *anywhere* in the original iterator\n    /// until the given `predicate` returns `false`.\n    ///\n    /// The `predicate` may be anything -- e.g. it could be checking a fact about the item, a\n    /// global condition unrelated to the item itself, or some combination thereof.\n    ///\n    /// If parallel calls to the `predicate` race and give different results, then the\n    /// `true` results will still take those particular items, while respecting the `false`\n    /// result from elsewhere to skip any further items.\n    ///\n    /// This is similar to [`Iterator::take_while`] without being constrained to the original\n    /// iterator order. The taken items will still maintain their relative order where that is\n    /// visible in `collect`, `reduce`, and similar outputs.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let result: Vec<_> = (0..100)\n    ///     .into_par_iter()\n    ///     .take_any_while(|x| *x < 50)\n    ///     .collect();\n    ///\n    /// assert!(result.len() <= 50);\n    /// assert!(result.windows(2).all(|w| w[0] < w[1]));\n    /// ```\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// use std::sync::atomic::AtomicUsize;\n    /// use std::sync::atomic::Ordering::Relaxed;\n    ///\n    /// // Collect any group of items that sum <= 1000\n    /// let quota = AtomicUsize::new(1000);\n    /// let result: Vec<_> = (0_usize..100)\n    ///     .into_par_iter()\n    ///     .take_any_while(|&x| {\n    ///         quota.fetch_update(Relaxed, Relaxed, |q| q.checked_sub(x))\n    ///             .is_ok()\n    ///     })\n    ///     .collect();\n    ///\n    /// let sum = result.iter().sum::<usize>();\n    /// assert!(matches!(sum, 902..=1000));\n    /// ```\n    fn take_any_while<P>(self, predicate: P) -> TakeAnyWhile<Self, P>\n    where\n        P: Fn(&Self::Item) -> bool + Sync + Send,\n    {\n        TakeAnyWhile::new(self, predicate)\n    }\n\n    /// Creates an iterator that skips elements from *anywhere* in the original iterator\n    /// until the given `predicate` returns `false`.\n    ///\n    /// The `predicate` may be anything -- e.g. it could be checking a fact about the item, a\n    /// global condition unrelated to the item itself, or some combination thereof.\n    ///\n    /// If parallel calls to the `predicate` race and give different results, then the\n    /// `true` results will still skip those particular items, while respecting the `false`\n    /// result from elsewhere to skip any further items.\n    ///\n    /// This is similar to [`Iterator::skip_while`] without being constrained to the original\n    /// iterator order. The remaining items will still maintain their relative order where that is\n    /// visible in `collect`, `reduce`, and similar outputs.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let result: Vec<_> = (0..100)\n    ///     .into_par_iter()\n    ///     .skip_any_while(|x| *x < 50)\n    ///     .collect();\n    ///\n    /// assert!(result.len() >= 50);\n    /// assert!(result.windows(2).all(|w| w[0] < w[1]));\n    /// ```\n    fn skip_any_while<P>(self, predicate: P) -> SkipAnyWhile<Self, P>\n    where\n        P: Fn(&Self::Item) -> bool + Sync + Send,\n    {\n        SkipAnyWhile::new(self, predicate)\n    }\n\n    /// Collects this iterator into a linked list of vectors.\n    ///\n    /// This is useful when you need to condense a parallel iterator into a collection,\n    /// but have no specific requirements for what that collection should be. If you\n    /// plan to store the collection longer-term, `Vec<T>` is, as always, likely the\n    /// best default choice, despite the overhead that comes from concatenating each\n    /// vector. Or, if this is an `IndexedParallelIterator`, you should also prefer to\n    /// just collect to a `Vec<T>`.\n    ///\n    /// Internally, most [`FromParallelIterator`]/[`ParallelExtend`] implementations\n    /// use this strategy; each job collecting their chunk of the iterator to a `Vec<T>`\n    /// and those chunks getting merged into a `LinkedList`, before then extending the\n    /// collection with each vector. This is a very efficient way to collect an\n    /// unindexed parallel iterator, without much intermediate data movement.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// # use std::collections::LinkedList;\n    /// use rayon::prelude::*;\n    ///\n    /// let result: LinkedList<Vec<_>> = (0..=100)\n    ///     .into_par_iter()\n    ///     .filter(|x| x % 2 == 0)\n    ///     .flat_map(|x| 0..x)\n    ///     .collect_vec_list();\n    ///\n    /// // `par_iter.collect_vec_list().into_iter().flatten()` turns\n    /// // a parallel iterator into a serial one\n    /// let total_len = result.into_iter().flatten().count();\n    /// assert_eq!(total_len, 2550);\n    /// ```\n    fn collect_vec_list(self) -> LinkedList<Vec<Self::Item>> {\n        match extend::fast_collect(self) {\n            Either::Left(vec) => {\n                let mut list = LinkedList::new();\n                if !vec.is_empty() {\n                    list.push_back(vec);\n                }\n                list\n            }\n            Either::Right(list) => list,\n        }\n    }\n\n    /// Internal method used to define the behavior of this parallel\n    /// iterator. You should not need to call this directly.\n    ///\n    /// This method causes the iterator `self` to start producing\n    /// items and to feed them to the consumer `consumer` one by one.\n    /// It may split the consumer before doing so to create the\n    /// opportunity to produce in parallel.\n    ///\n    /// See the [README] for more details on the internals of parallel\n    /// iterators.\n    ///\n    /// [README]: https://github.com/rayon-rs/rayon/blob/main/src/iter/plumbing/README.md\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>;\n\n    /// Internal method used to define the behavior of this parallel\n    /// iterator. You should not need to call this directly.\n    ///\n    /// Returns the number of items produced by this iterator, if known\n    /// statically. This can be used by consumers to trigger special fast\n    /// paths. Therefore, if `Some(_)` is returned, this iterator must only\n    /// use the (indexed) `Consumer` methods when driving a consumer, such\n    /// as `split_at()`. Calling `UnindexedConsumer::split_off_left()` or\n    /// other `UnindexedConsumer` methods -- or returning an inaccurate\n    /// value -- may result in panics.\n    ///\n    /// This method is currently used to optimize `collect` for want\n    /// of true Rust specialization; it may be removed when\n    /// specialization is stable.\n    fn opt_len(&self) -> Option<usize> {\n        None\n    }\n}\n\nimpl<T: ParallelIterator> IntoParallelIterator for T {\n    type Iter = T;\n    type Item = T::Item;\n\n    fn into_par_iter(self) -> T {\n        self\n    }\n}\n\n/// An iterator that supports \"random access\" to its data, meaning\n/// that you can split it at arbitrary indices and draw data from\n/// those points.\n///\n/// **Note:** Not implemented for `u64`, `i64`, `u128`, or `i128` ranges\n// Waiting for `ExactSizeIterator::is_empty` to be stabilized. See rust-lang/rust#35428\n#[allow(clippy::len_without_is_empty)]\npub trait IndexedParallelIterator: ParallelIterator {\n    /// Divides an iterator into sequential blocks of exponentially-increasing size.\n    ///\n    /// Normally, parallel iterators are recursively divided into tasks in parallel.\n    /// This adaptor changes the default behavior by splitting the iterator into a **sequence**\n    /// of parallel iterators of increasing sizes.\n    /// Sizes grow exponentially in order to avoid creating\n    /// too many blocks. This also allows to balance the current block with all previous ones.\n    ///\n    /// This can have many applications but the most notable ones are:\n    /// - better performance with [`find_first()`][ParallelIterator::find_first]\n    /// - more predictable performance with [`find_any()`][ParallelIterator::find_any]\n    ///   or any interruptible computation\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// assert_eq!((0..10_000).into_par_iter()\n    ///                       .by_exponential_blocks()\n    ///                       .find_first(|&e| e==4_999), Some(4_999))\n    /// ```\n    ///\n    /// In this example, without blocks, rayon will split the initial range into two but all work\n    /// on the right hand side (from 5,000 onwards) is **useless** since the sequential algorithm\n    /// never goes there. This means that if two threads are used there will be **no** speedup **at\n    /// all**.\n    ///\n    /// `by_exponential_blocks` on the other hand will start with the leftmost range from 0\n    /// to `p` (threads number), continue with p to 3p, the 3p to 7p...\n    ///\n    /// Each subrange is treated in parallel, while all subranges are treated sequentially.\n    /// We therefore ensure a logarithmic number of blocks (and overhead) while guaranteeing\n    /// we stop at the first block containing the searched data.\n    fn by_exponential_blocks(self) -> ExponentialBlocks<Self> {\n        ExponentialBlocks::new(self)\n    }\n\n    /// Divides an iterator into sequential blocks of the given size.\n    ///\n    /// Normally, parallel iterators are recursively divided into tasks in parallel.\n    /// This adaptor changes the default behavior by splitting the iterator into a **sequence**\n    /// of parallel iterators of given `block_size`.\n    /// The main application is to obtain better\n    /// memory locality (especially if the reduce operation re-use folded data).\n    ///\n    /// **Panics** if `block_size` is 0.\n    ///\n    /// # Example\n    /// ```\n    /// use rayon::prelude::*;\n    /// // during most reductions v1 and v2 fit the cache\n    /// let v = (0u32..10_000_000)\n    ///     .into_par_iter()\n    ///     .by_uniform_blocks(1_000_000)\n    ///     .fold(Vec::new, |mut v, e| { v.push(e); v})\n    ///     .reduce(Vec::new, |mut v1, mut v2| { v1.append(&mut v2); v1});\n    /// assert_eq!(v, (0u32..10_000_000).collect::<Vec<u32>>());\n    /// ```\n    #[track_caller]\n    fn by_uniform_blocks(self, block_size: usize) -> UniformBlocks<Self> {\n        assert!(block_size != 0, \"block_size must not be zero\");\n        UniformBlocks::new(self, block_size)\n    }\n\n    /// Collects the results of the iterator into the specified\n    /// vector. The vector is always cleared before execution\n    /// begins. If possible, reusing the vector across calls can lead\n    /// to better performance since it reuses the same backing buffer.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// // any prior data will be cleared\n    /// let mut vec = vec![-1, -2, -3];\n    ///\n    /// (0..5).into_par_iter()\n    ///     .collect_into_vec(&mut vec);\n    ///\n    /// assert_eq!(vec, [0, 1, 2, 3, 4]);\n    /// ```\n    fn collect_into_vec(self, target: &mut Vec<Self::Item>) {\n        collect::collect_into_vec(self, target);\n    }\n\n    /// Unzips the results of the iterator into the specified\n    /// vectors. The vectors are always cleared before execution\n    /// begins. If possible, reusing the vectors across calls can lead\n    /// to better performance since they reuse the same backing buffer.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// // any prior data will be cleared\n    /// let mut left = vec![42; 10];\n    /// let mut right = vec![-1; 10];\n    ///\n    /// (10..15).into_par_iter()\n    ///     .enumerate()\n    ///     .unzip_into_vecs(&mut left, &mut right);\n    ///\n    /// assert_eq!(left, [0, 1, 2, 3, 4]);\n    /// assert_eq!(right, [10, 11, 12, 13, 14]);\n    /// ```\n    fn unzip_into_vecs<A, B>(self, left: &mut Vec<A>, right: &mut Vec<B>)\n    where\n        Self: IndexedParallelIterator<Item = (A, B)>,\n        A: Send,\n        B: Send,\n    {\n        collect::unzip_into_vecs(self, left, right);\n    }\n\n    /// Iterates over tuples `(A, B)`, where the items `A` are from\n    /// this iterator and `B` are from the iterator given as argument.\n    /// Like the `zip` method on ordinary iterators, if the two\n    /// iterators are of unequal length, you only get the items they\n    /// have in common.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let result: Vec<_> = (1..4)\n    ///     .into_par_iter()\n    ///     .zip(vec!['a', 'b', 'c'])\n    ///     .collect();\n    ///\n    /// assert_eq!(result, [(1, 'a'), (2, 'b'), (3, 'c')]);\n    /// ```\n    fn zip<Z>(self, zip_op: Z) -> Zip<Self, Z::Iter>\n    where\n        Z: IntoParallelIterator<Iter: IndexedParallelIterator>,\n    {\n        Zip::new(self, zip_op.into_par_iter())\n    }\n\n    /// The same as `Zip`, but requires that both iterators have the same length.\n    ///\n    /// # Panics\n    /// Will panic if `self` and `zip_op` are not the same length.\n    ///\n    /// ```should_panic\n    /// use rayon::prelude::*;\n    ///\n    /// let one = [1u8];\n    /// let two = [2u8, 2];\n    /// let one_iter = one.par_iter();\n    /// let two_iter = two.par_iter();\n    ///\n    /// // this will panic\n    /// let zipped: Vec<(&u8, &u8)> = one_iter.zip_eq(two_iter).collect();\n    ///\n    /// // we should never get here\n    /// assert_eq!(1, zipped.len());\n    /// ```\n    #[track_caller]\n    fn zip_eq<Z>(self, zip_op: Z) -> ZipEq<Self, Z::Iter>\n    where\n        Z: IntoParallelIterator<Iter: IndexedParallelIterator>,\n    {\n        let zip_op_iter = zip_op.into_par_iter();\n        assert_eq!(\n            self.len(),\n            zip_op_iter.len(),\n            \"iterators must have the same length\"\n        );\n        ZipEq::new(self, zip_op_iter)\n    }\n\n    /// Interleaves elements of this iterator and the other given\n    /// iterator. Alternately yields elements from this iterator and\n    /// the given iterator, until both are exhausted. If one iterator\n    /// is exhausted before the other, the last elements are provided\n    /// from the other.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let (x, y) = (vec![1, 2], vec![3, 4, 5, 6]);\n    /// let r: Vec<i32> = x.into_par_iter().interleave(y).collect();\n    /// assert_eq!(r, vec![1, 3, 2, 4, 5, 6]);\n    /// ```\n    fn interleave<I>(self, other: I) -> Interleave<Self, I::Iter>\n    where\n        I: IntoParallelIterator<Item = Self::Item, Iter: IndexedParallelIterator>,\n    {\n        Interleave::new(self, other.into_par_iter())\n    }\n\n    /// Interleaves elements of this iterator and the other given\n    /// iterator, until one is exhausted.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let (x, y) = (vec![1, 2, 3, 4], vec![5, 6]);\n    /// let r: Vec<i32> = x.into_par_iter().interleave_shortest(y).collect();\n    /// assert_eq!(r, vec![1, 5, 2, 6, 3]);\n    /// ```\n    fn interleave_shortest<I>(self, other: I) -> InterleaveShortest<Self, I::Iter>\n    where\n        I: IntoParallelIterator<Item = Self::Item, Iter: IndexedParallelIterator>,\n    {\n        InterleaveShortest::new(self, other.into_par_iter())\n    }\n\n    /// Splits an iterator up into fixed-size chunks.\n    ///\n    /// Returns an iterator that returns `Vec`s of the given number of elements.\n    /// If the number of elements in the iterator is not divisible by `chunk_size`,\n    /// the last chunk may be shorter than `chunk_size`.\n    ///\n    /// See also [`par_chunks()`] and [`par_chunks_mut()`] for similar behavior on\n    /// slices, without having to allocate intermediate `Vec`s for the chunks.\n    ///\n    /// [`par_chunks()`]: crate::slice::ParallelSlice::par_chunks()\n    /// [`par_chunks_mut()`]: crate::slice::ParallelSliceMut::par_chunks_mut()\n    ///\n    /// **Panics** if `chunk_size` is 0.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let a = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n    /// let r: Vec<Vec<i32>> = a.into_par_iter().chunks(3).collect();\n    /// assert_eq!(r, vec![vec![1,2,3], vec![4,5,6], vec![7,8,9], vec![10]]);\n    /// ```\n    #[track_caller]\n    fn chunks(self, chunk_size: usize) -> Chunks<Self> {\n        assert!(chunk_size != 0, \"chunk_size must not be zero\");\n        Chunks::new(self, chunk_size)\n    }\n\n    /// Splits an iterator into fixed-size chunks, performing a sequential [`fold()`] on\n    /// each chunk.\n    ///\n    /// Returns an iterator that produces a folded result for each chunk of items\n    /// produced by this iterator.\n    ///\n    /// This works essentially like:\n    ///\n    /// ```text\n    /// iter.chunks(chunk_size)\n    ///     .map(|chunk|\n    ///         chunk.into_iter()\n    ///             .fold(identity, fold_op)\n    ///     )\n    /// ```\n    ///\n    /// except there is no per-chunk allocation overhead.\n    ///\n    /// [`fold()`]: std::iter::Iterator#method.fold\n    ///\n    /// **Panics** if `chunk_size` is 0.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let nums = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n    /// let chunk_sums = nums.into_par_iter().fold_chunks(2, || 0, |a, n| a + n).collect::<Vec<_>>();\n    /// assert_eq!(chunk_sums, vec![3, 7, 11, 15, 19]);\n    /// ```\n    #[track_caller]\n    fn fold_chunks<T, ID, F>(\n        self,\n        chunk_size: usize,\n        identity: ID,\n        fold_op: F,\n    ) -> FoldChunks<Self, ID, F>\n    where\n        ID: Fn() -> T + Send + Sync,\n        F: Fn(T, Self::Item) -> T + Send + Sync,\n        T: Send,\n    {\n        assert!(chunk_size != 0, \"chunk_size must not be zero\");\n        FoldChunks::new(self, chunk_size, identity, fold_op)\n    }\n\n    /// Splits an iterator into fixed-size chunks, performing a sequential [`fold()`] on\n    /// each chunk.\n    ///\n    /// Returns an iterator that produces a folded result for each chunk of items\n    /// produced by this iterator.\n    ///\n    /// This works essentially like `fold_chunks(chunk_size, || init.clone(), fold_op)`,\n    /// except it doesn't require the `init` type to be `Sync`, nor any other form of\n    /// added synchronization.\n    ///\n    /// [`fold()`]: std::iter::Iterator#method.fold\n    ///\n    /// **Panics** if `chunk_size` is 0.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let nums = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n    /// let chunk_sums = nums.into_par_iter().fold_chunks_with(2, 0, |a, n| a + n).collect::<Vec<_>>();\n    /// assert_eq!(chunk_sums, vec![3, 7, 11, 15, 19]);\n    /// ```\n    #[track_caller]\n    fn fold_chunks_with<T, F>(\n        self,\n        chunk_size: usize,\n        init: T,\n        fold_op: F,\n    ) -> FoldChunksWith<Self, T, F>\n    where\n        T: Send + Clone,\n        F: Fn(T, Self::Item) -> T + Send + Sync,\n    {\n        assert!(chunk_size != 0, \"chunk_size must not be zero\");\n        FoldChunksWith::new(self, chunk_size, init, fold_op)\n    }\n\n    /// Lexicographically compares the elements of this `ParallelIterator` with those of\n    /// another.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// use std::cmp::Ordering::*;\n    ///\n    /// let x = vec![1, 2, 3];\n    /// assert_eq!(x.par_iter().cmp(&vec![1, 3, 0]), Less);\n    /// assert_eq!(x.par_iter().cmp(&vec![1, 2, 3]), Equal);\n    /// assert_eq!(x.par_iter().cmp(&vec![1, 2]), Greater);\n    /// ```\n    fn cmp<I>(self, other: I) -> Ordering\n    where\n        I: IntoParallelIterator<Item = Self::Item, Iter: IndexedParallelIterator>,\n        Self::Item: Ord,\n    {\n        #[inline]\n        fn ordering<T: Ord>((x, y): (T, T)) -> Ordering {\n            Ord::cmp(&x, &y)\n        }\n\n        #[inline]\n        fn inequal(&ord: &Ordering) -> bool {\n            ord != Ordering::Equal\n        }\n\n        let other = other.into_par_iter();\n        let ord_len = self.len().cmp(&other.len());\n        self.zip(other)\n            .map(ordering)\n            .find_first(inequal)\n            .unwrap_or(ord_len)\n    }\n\n    /// Lexicographically compares the elements of this `ParallelIterator` with those of\n    /// another.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// use std::cmp::Ordering::*;\n    ///\n    /// let x = vec![1.0, 2.0, 3.0];\n    /// assert_eq!(x.par_iter().partial_cmp(&vec![1.0, 3.0, 0.0]), Some(Less));\n    /// assert_eq!(x.par_iter().partial_cmp(&vec![1.0, 2.0, 3.0]), Some(Equal));\n    /// assert_eq!(x.par_iter().partial_cmp(&vec![1.0, 2.0]), Some(Greater));\n    /// assert_eq!(x.par_iter().partial_cmp(&vec![1.0, f64::NAN]), None);\n    /// ```\n    fn partial_cmp<I>(self, other: I) -> Option<Ordering>\n    where\n        I: IntoParallelIterator<Iter: IndexedParallelIterator>,\n        Self::Item: PartialOrd<I::Item>,\n    {\n        #[inline]\n        fn ordering<T: PartialOrd<U>, U>((x, y): (T, U)) -> Option<Ordering> {\n            PartialOrd::partial_cmp(&x, &y)\n        }\n\n        #[inline]\n        fn inequal(&ord: &Option<Ordering>) -> bool {\n            ord != Some(Ordering::Equal)\n        }\n\n        let other = other.into_par_iter();\n        let ord_len = self.len().cmp(&other.len());\n        self.zip(other)\n            .map(ordering)\n            .find_first(inequal)\n            .unwrap_or(Some(ord_len))\n    }\n\n    /// Determines if the elements of this `ParallelIterator`\n    /// are equal to those of another\n    fn eq<I>(self, other: I) -> bool\n    where\n        I: IntoParallelIterator<Iter: IndexedParallelIterator>,\n        Self::Item: PartialEq<I::Item>,\n    {\n        #[inline]\n        fn eq<T: PartialEq<U>, U>((x, y): (T, U)) -> bool {\n            PartialEq::eq(&x, &y)\n        }\n\n        let other = other.into_par_iter();\n        self.len() == other.len() && self.zip(other).all(eq)\n    }\n\n    /// Determines if the elements of this `ParallelIterator`\n    /// are unequal to those of another\n    fn ne<I>(self, other: I) -> bool\n    where\n        I: IntoParallelIterator<Iter: IndexedParallelIterator>,\n        Self::Item: PartialEq<I::Item>,\n    {\n        !self.eq(other)\n    }\n\n    /// Determines if the elements of this `ParallelIterator`\n    /// are lexicographically less than those of another.\n    fn lt<I>(self, other: I) -> bool\n    where\n        I: IntoParallelIterator<Iter: IndexedParallelIterator>,\n        Self::Item: PartialOrd<I::Item>,\n    {\n        self.partial_cmp(other) == Some(Ordering::Less)\n    }\n\n    /// Determines if the elements of this `ParallelIterator`\n    /// are less than or equal to those of another.\n    fn le<I>(self, other: I) -> bool\n    where\n        I: IntoParallelIterator<Iter: IndexedParallelIterator>,\n        Self::Item: PartialOrd<I::Item>,\n    {\n        let ord = self.partial_cmp(other);\n        ord == Some(Ordering::Equal) || ord == Some(Ordering::Less)\n    }\n\n    /// Determines if the elements of this `ParallelIterator`\n    /// are lexicographically greater than those of another.\n    fn gt<I>(self, other: I) -> bool\n    where\n        I: IntoParallelIterator<Iter: IndexedParallelIterator>,\n        Self::Item: PartialOrd<I::Item>,\n    {\n        self.partial_cmp(other) == Some(Ordering::Greater)\n    }\n\n    /// Determines if the elements of this `ParallelIterator`\n    /// are greater than or equal to those of another.\n    fn ge<I>(self, other: I) -> bool\n    where\n        I: IntoParallelIterator<Iter: IndexedParallelIterator>,\n        Self::Item: PartialOrd<I::Item>,\n    {\n        let ord = self.partial_cmp(other);\n        ord == Some(Ordering::Equal) || ord == Some(Ordering::Greater)\n    }\n\n    /// Yields an index along with each item.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let chars = vec!['a', 'b', 'c'];\n    /// let result: Vec<_> = chars\n    ///     .into_par_iter()\n    ///     .enumerate()\n    ///     .collect();\n    ///\n    /// assert_eq!(result, [(0, 'a'), (1, 'b'), (2, 'c')]);\n    /// ```\n    fn enumerate(self) -> Enumerate<Self> {\n        Enumerate::new(self)\n    }\n\n    /// Creates an iterator that steps by the given amount\n    ///\n    /// # Examples\n    ///\n    /// ```\n    ///use rayon::prelude::*;\n    ///\n    /// let range = (3..10);\n    /// let result: Vec<i32> = range\n    ///    .into_par_iter()\n    ///    .step_by(3)\n    ///    .collect();\n    ///\n    /// assert_eq!(result, [3, 6, 9])\n    /// ```\n    fn step_by(self, step: usize) -> StepBy<Self> {\n        StepBy::new(self, step)\n    }\n\n    /// Creates an iterator that skips the first `n` elements.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let result: Vec<_> = (0..100)\n    ///     .into_par_iter()\n    ///     .skip(95)\n    ///     .collect();\n    ///\n    /// assert_eq!(result, [95, 96, 97, 98, 99]);\n    /// ```\n    fn skip(self, n: usize) -> Skip<Self> {\n        Skip::new(self, n)\n    }\n\n    /// Creates an iterator that yields the first `n` elements.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let result: Vec<_> = (0..100)\n    ///     .into_par_iter()\n    ///     .take(5)\n    ///     .collect();\n    ///\n    /// assert_eq!(result, [0, 1, 2, 3, 4]);\n    /// ```\n    fn take(self, n: usize) -> Take<Self> {\n        Take::new(self, n)\n    }\n\n    /// Searches for **some** item in the parallel iterator that\n    /// matches the given predicate, and returns its index.  Like\n    /// `ParallelIterator::find_any`, the parallel search will not\n    /// necessarily find the **first** match, and once a match is\n    /// found we'll attempt to stop processing any more.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [1, 2, 3, 3];\n    ///\n    /// let i = a.par_iter().position_any(|&x| x == 3).expect(\"found\");\n    /// assert!(i == 2 || i == 3);\n    ///\n    /// assert_eq!(a.par_iter().position_any(|&x| x == 100), None);\n    /// ```\n    fn position_any<P>(self, predicate: P) -> Option<usize>\n    where\n        P: Fn(Self::Item) -> bool + Sync + Send,\n    {\n        #[inline]\n        fn check(&(_, p): &(usize, bool)) -> bool {\n            p\n        }\n\n        let (i, _) = self.map(predicate).enumerate().find_any(check)?;\n        Some(i)\n    }\n\n    /// Searches for the sequentially **first** item in the parallel iterator\n    /// that matches the given predicate, and returns its index.\n    ///\n    /// Like `ParallelIterator::find_first`, once a match is found,\n    /// all attempts to the right of the match will be stopped, while\n    /// attempts to the left must continue in case an earlier match\n    /// is found.\n    ///\n    /// Note that not all parallel iterators have a useful order, much like\n    /// sequential `HashMap` iteration, so \"first\" may be nebulous.  If you\n    /// just want the first match that discovered anywhere in the iterator,\n    /// `position_any` is a better choice.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [1, 2, 3, 3];\n    ///\n    /// assert_eq!(a.par_iter().position_first(|&x| x == 3), Some(2));\n    ///\n    /// assert_eq!(a.par_iter().position_first(|&x| x == 100), None);\n    /// ```\n    fn position_first<P>(self, predicate: P) -> Option<usize>\n    where\n        P: Fn(Self::Item) -> bool + Sync + Send,\n    {\n        #[inline]\n        fn check(&(_, p): &(usize, bool)) -> bool {\n            p\n        }\n\n        let (i, _) = self.map(predicate).enumerate().find_first(check)?;\n        Some(i)\n    }\n\n    /// Searches for the sequentially **last** item in the parallel iterator\n    /// that matches the given predicate, and returns its index.\n    ///\n    /// Like `ParallelIterator::find_last`, once a match is found,\n    /// all attempts to the left of the match will be stopped, while\n    /// attempts to the right must continue in case a later match\n    /// is found.\n    ///\n    /// Note that not all parallel iterators have a useful order, much like\n    /// sequential `HashMap` iteration, so \"last\" may be nebulous.  When the\n    /// order doesn't actually matter to you, `position_any` is a better\n    /// choice.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let a = [1, 2, 3, 3];\n    ///\n    /// assert_eq!(a.par_iter().position_last(|&x| x == 3), Some(3));\n    ///\n    /// assert_eq!(a.par_iter().position_last(|&x| x == 100), None);\n    /// ```\n    fn position_last<P>(self, predicate: P) -> Option<usize>\n    where\n        P: Fn(Self::Item) -> bool + Sync + Send,\n    {\n        #[inline]\n        fn check(&(_, p): &(usize, bool)) -> bool {\n            p\n        }\n\n        let (i, _) = self.map(predicate).enumerate().find_last(check)?;\n        Some(i)\n    }\n\n    #[doc(hidden)]\n    #[deprecated(\n        note = \"parallel `position` does not search in order -- use `position_any`, \\\\\n                `position_first`, or `position_last`\"\n    )]\n    fn position<P>(self, predicate: P) -> Option<usize>\n    where\n        P: Fn(Self::Item) -> bool + Sync + Send,\n    {\n        self.position_any(predicate)\n    }\n\n    /// Searches for items in the parallel iterator that match the given\n    /// predicate, and returns their indices.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let primes = vec![2, 3, 5, 7, 11, 13, 17, 19, 23, 29];\n    ///\n    /// // Find the positions of primes congruent to 1 modulo 6\n    /// let p1mod6: Vec<_> = primes.par_iter().positions(|&p| p % 6 == 1).collect();\n    /// assert_eq!(p1mod6, [3, 5, 7]); // primes 7, 13, and 19\n    ///\n    /// // Find the positions of primes congruent to 5 modulo 6\n    /// let p5mod6: Vec<_> = primes.par_iter().positions(|&p| p % 6 == 5).collect();\n    /// assert_eq!(p5mod6, [2, 4, 6, 8, 9]); // primes 5, 11, 17, 23, and 29\n    /// ```\n    fn positions<P>(self, predicate: P) -> Positions<Self, P>\n    where\n        P: Fn(Self::Item) -> bool + Sync + Send,\n    {\n        Positions::new(self, predicate)\n    }\n\n    /// Produces a new iterator with the elements of this iterator in\n    /// reverse order.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let result: Vec<_> = (0..5)\n    ///     .into_par_iter()\n    ///     .rev()\n    ///     .collect();\n    ///\n    /// assert_eq!(result, [4, 3, 2, 1, 0]);\n    /// ```\n    fn rev(self) -> Rev<Self> {\n        Rev::new(self)\n    }\n\n    /// Sets the minimum length of iterators desired to process in each\n    /// rayon job.  Rayon will not split any smaller than this length, but\n    /// of course an iterator could already be smaller to begin with.\n    ///\n    /// Producers like `zip` and `interleave` will use greater of the two\n    /// minimums.\n    /// Chained iterators and iterators inside `flat_map` may each use\n    /// their own minimum length.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let min = (0..1_000_000)\n    ///     .into_par_iter()\n    ///     .with_min_len(1234)\n    ///     .fold(|| 0, |acc, _| acc + 1) // count how many are in this segment\n    ///     .min().unwrap();\n    ///\n    /// assert!(min >= 1234);\n    /// ```\n    fn with_min_len(self, min: usize) -> MinLen<Self> {\n        MinLen::new(self, min)\n    }\n\n    /// Sets the maximum length of iterators desired to process in each\n    /// rayon job.  Rayon will try to split at least below this length,\n    /// unless that would put it below the length from `with_min_len()`.\n    /// For example, given min=10 and max=15, a length of 16 will not be\n    /// split any further.\n    ///\n    /// Producers like `zip` and `interleave` will use lesser of the two\n    /// maximums.\n    /// Chained iterators and iterators inside `flat_map` may each use\n    /// their own maximum length.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let max = (0..1_000_000)\n    ///     .into_par_iter()\n    ///     .with_max_len(1234)\n    ///     .fold(|| 0, |acc, _| acc + 1) // count how many are in this segment\n    ///     .max().unwrap();\n    ///\n    /// assert!(max <= 1234);\n    /// ```\n    fn with_max_len(self, max: usize) -> MaxLen<Self> {\n        MaxLen::new(self, max)\n    }\n\n    /// Produces an exact count of how many items this iterator will\n    /// produce, presuming no panic occurs.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let par_iter = (0..100).into_par_iter().zip(vec![0; 10]);\n    /// assert_eq!(par_iter.len(), 10);\n    ///\n    /// let vec: Vec<_> = par_iter.collect();\n    /// assert_eq!(vec.len(), 10);\n    /// ```\n    fn len(&self) -> usize;\n\n    /// Internal method used to define the behavior of this parallel\n    /// iterator. You should not need to call this directly.\n    ///\n    /// This method causes the iterator `self` to start producing\n    /// items and to feed them to the consumer `consumer` one by one.\n    /// It may split the consumer before doing so to create the\n    /// opportunity to produce in parallel. If a split does happen, it\n    /// will inform the consumer of the index where the split should\n    /// occur (unlike `ParallelIterator::drive_unindexed()`).\n    ///\n    /// See the [README] for more details on the internals of parallel\n    /// iterators.\n    ///\n    /// [README]: https://github.com/rayon-rs/rayon/blob/main/src/iter/plumbing/README.md\n    fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result;\n\n    /// Internal method used to define the behavior of this parallel\n    /// iterator. You should not need to call this directly.\n    ///\n    /// This method converts the iterator into a producer P and then\n    /// invokes `callback.callback()` with P. Note that the type of\n    /// this producer is not defined as part of the API, since\n    /// `callback` must be defined generically for all producers. This\n    /// allows the producer type to contain references; it also means\n    /// that parallel iterators can adjust that type without causing a\n    /// breaking change.\n    ///\n    /// See the [README] for more details on the internals of parallel\n    /// iterators.\n    ///\n    /// [README]: https://github.com/rayon-rs/rayon/blob/main/src/iter/plumbing/README.md\n    fn with_producer<CB: ProducerCallback<Self::Item>>(self, callback: CB) -> CB::Output;\n}\n\n/// `FromParallelIterator` implements the creation of a collection\n/// from a [`ParallelIterator`]. By implementing\n/// `FromParallelIterator` for a given type, you define how it will be\n/// created from an iterator.\n///\n/// `FromParallelIterator` is used through [`ParallelIterator`]'s [`collect()`] method.\n///\n/// [`collect()`]: ParallelIterator::collect()\n///\n/// # Examples\n///\n/// Implementing `FromParallelIterator` for your type:\n///\n/// ```\n/// use rayon::prelude::*;\n///\n/// struct BlackHole {\n///     mass: usize,\n/// }\n///\n/// impl<T: Send> FromParallelIterator<T> for BlackHole {\n///     fn from_par_iter<I>(par_iter: I) -> Self\n///         where I: IntoParallelIterator<Item = T>\n///     {\n///         let par_iter = par_iter.into_par_iter();\n///         BlackHole {\n///             mass: par_iter.count() * size_of::<T>(),\n///         }\n///     }\n/// }\n///\n/// let bh: BlackHole = (0i32..1000).into_par_iter().collect();\n/// assert_eq!(bh.mass, 4000);\n/// ```\npub trait FromParallelIterator<T>\nwhere\n    T: Send,\n{\n    /// Creates an instance of the collection from the parallel iterator `par_iter`.\n    ///\n    /// If your collection is not naturally parallel, the easiest (and\n    /// fastest) way to do this is often to collect `par_iter` into a\n    /// [`LinkedList`] (via [`collect_vec_list`]) or another intermediate\n    /// data structure and then sequentially extend your collection. However,\n    /// a more 'native' technique is to use the [`par_iter.fold`] or\n    /// [`par_iter.fold_with`] methods to create the collection.\n    /// Alternatively, if your collection is 'natively' parallel, you\n    /// can use [`par_iter.for_each`] to process each element in turn.\n    ///\n    /// [`LinkedList`]: std::collections::LinkedList\n    /// [`collect_vec_list`]: ParallelIterator::collect_vec_list\n    /// [`par_iter.fold`]: ParallelIterator::fold()\n    /// [`par_iter.fold_with`]: ParallelIterator::fold_with()\n    /// [`par_iter.for_each`]: ParallelIterator::for_each()\n    fn from_par_iter<I>(par_iter: I) -> Self\n    where\n        I: IntoParallelIterator<Item = T>;\n}\n\n/// `ParallelExtend` extends an existing collection with items from a [`ParallelIterator`].\n///\n/// # Examples\n///\n/// Implementing `ParallelExtend` for your type:\n///\n/// ```\n/// use rayon::prelude::*;\n///\n/// struct BlackHole {\n///     mass: usize,\n/// }\n///\n/// impl<T: Send> ParallelExtend<T> for BlackHole {\n///     fn par_extend<I>(&mut self, par_iter: I)\n///         where I: IntoParallelIterator<Item = T>\n///     {\n///         let par_iter = par_iter.into_par_iter();\n///         self.mass += par_iter.count() * size_of::<T>();\n///     }\n/// }\n///\n/// let mut bh = BlackHole { mass: 0 };\n/// bh.par_extend(0i32..1000);\n/// assert_eq!(bh.mass, 4000);\n/// bh.par_extend(0i64..10);\n/// assert_eq!(bh.mass, 4080);\n/// ```\npub trait ParallelExtend<T>\nwhere\n    T: Send,\n{\n    /// Extends an instance of the collection with the elements drawn\n    /// from the parallel iterator `par_iter`.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let mut vec = vec![];\n    /// vec.par_extend(0..5);\n    /// vec.par_extend((0..5).into_par_iter().map(|i| i * i));\n    /// assert_eq!(vec, [0, 1, 2, 3, 4, 0, 1, 4, 9, 16]);\n    /// ```\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = T>;\n}\n\n/// `ParallelDrainFull` creates a parallel iterator that moves all items\n/// from a collection while retaining the original capacity.\n///\n/// Types which are indexable typically implement [`ParallelDrainRange`]\n/// instead, where you can drain fully with `par_drain(..)`.\npub trait ParallelDrainFull {\n    /// The draining parallel iterator type that will be created.\n    type Iter: ParallelIterator<Item = Self::Item>;\n\n    /// The type of item that the parallel iterator will produce.\n    /// This is usually the same as `IntoParallelIterator::Item`.\n    type Item: Send;\n\n    /// Returns a draining parallel iterator over an entire collection.\n    ///\n    /// When the iterator is dropped, all items are removed, even if the\n    /// iterator was not fully consumed. If the iterator is leaked, for example\n    /// using `std::mem::forget`, it is unspecified how many items are removed.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// use std::collections::{BinaryHeap, HashSet};\n    ///\n    /// let squares: HashSet<i32> = (0..10).map(|x| x * x).collect();\n    ///\n    /// let mut heap: BinaryHeap<_> = squares.iter().copied().collect();\n    /// assert_eq!(\n    ///     // heaps are drained in arbitrary order\n    ///     heap.par_drain()\n    ///         .inspect(|x| assert!(squares.contains(x)))\n    ///         .count(),\n    ///     squares.len(),\n    /// );\n    /// assert!(heap.is_empty());\n    /// assert!(heap.capacity() >= squares.len());\n    /// ```\n    fn par_drain(self) -> Self::Iter;\n}\n\n/// `ParallelDrainRange` creates a parallel iterator that moves a range of items\n/// from a collection while retaining the original capacity.\n///\n/// Types which are not indexable may implement [`ParallelDrainFull`] instead.\npub trait ParallelDrainRange<Idx = usize> {\n    /// The draining parallel iterator type that will be created.\n    type Iter: ParallelIterator<Item = Self::Item>;\n\n    /// The type of item that the parallel iterator will produce.\n    /// This is usually the same as `IntoParallelIterator::Item`.\n    type Item: Send;\n\n    /// Returns a draining parallel iterator over a range of the collection.\n    ///\n    /// When the iterator is dropped, all items in the range are removed, even\n    /// if the iterator was not fully consumed. If the iterator is leaked, for\n    /// example using `std::mem::forget`, it is unspecified how many items are\n    /// removed.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let squares: Vec<i32> = (0..10).map(|x| x * x).collect();\n    ///\n    /// println!(\"RangeFull\");\n    /// let mut vec = squares.clone();\n    /// assert!(vec.par_drain(..)\n    ///            .eq(squares.par_iter().copied()));\n    /// assert!(vec.is_empty());\n    /// assert!(vec.capacity() >= squares.len());\n    ///\n    /// println!(\"RangeFrom\");\n    /// let mut vec = squares.clone();\n    /// assert!(vec.par_drain(5..)\n    ///            .eq(squares[5..].par_iter().copied()));\n    /// assert_eq!(&vec[..], &squares[..5]);\n    /// assert!(vec.capacity() >= squares.len());\n    ///\n    /// println!(\"RangeTo\");\n    /// let mut vec = squares.clone();\n    /// assert!(vec.par_drain(..5)\n    ///            .eq(squares[..5].par_iter().copied()));\n    /// assert_eq!(&vec[..], &squares[5..]);\n    /// assert!(vec.capacity() >= squares.len());\n    ///\n    /// println!(\"RangeToInclusive\");\n    /// let mut vec = squares.clone();\n    /// assert!(vec.par_drain(..=5)\n    ///            .eq(squares[..=5].par_iter().copied()));\n    /// assert_eq!(&vec[..], &squares[6..]);\n    /// assert!(vec.capacity() >= squares.len());\n    ///\n    /// println!(\"Range\");\n    /// let mut vec = squares.clone();\n    /// assert!(vec.par_drain(3..7)\n    ///            .eq(squares[3..7].par_iter().copied()));\n    /// assert_eq!(&vec[..3], &squares[..3]);\n    /// assert_eq!(&vec[3..], &squares[7..]);\n    /// assert!(vec.capacity() >= squares.len());\n    ///\n    /// println!(\"RangeInclusive\");\n    /// let mut vec = squares.clone();\n    /// assert!(vec.par_drain(3..=7)\n    ///            .eq(squares[3..=7].par_iter().copied()));\n    /// assert_eq!(&vec[..3], &squares[..3]);\n    /// assert_eq!(&vec[3..], &squares[8..]);\n    /// assert!(vec.capacity() >= squares.len());\n    /// ```\n    fn par_drain<R: RangeBounds<Idx>>(self, range: R) -> Self::Iter;\n}\n\n/// We hide the `Try` trait in a private module, as it's only meant to be a\n/// stable clone of the standard library's `Try` trait, as yet unstable.\nmod private {\n    use std::convert::Infallible;\n    use std::ops::ControlFlow::{self, Break, Continue};\n    use std::task::Poll;\n\n    /// Clone of `std::ops::Try`.\n    ///\n    /// Implementing this trait is not permitted outside of `rayon`.\n    pub trait Try {\n        private_decl! {}\n\n        type Output;\n        type Residual;\n\n        fn from_output(output: Self::Output) -> Self;\n\n        fn from_residual(residual: Self::Residual) -> Self;\n\n        fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;\n    }\n\n    impl<B, C> Try for ControlFlow<B, C> {\n        private_impl! {}\n\n        type Output = C;\n        type Residual = ControlFlow<B, Infallible>;\n\n        fn from_output(output: Self::Output) -> Self {\n            Continue(output)\n        }\n\n        fn from_residual(residual: Self::Residual) -> Self {\n            match residual {\n                Break(b) => Break(b),\n                #[allow(unreachable_patterns)]\n                Continue(_) => unreachable!(),\n            }\n        }\n\n        fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {\n            match self {\n                Continue(c) => Continue(c),\n                Break(b) => Break(Break(b)),\n            }\n        }\n    }\n\n    impl<T> Try for Option<T> {\n        private_impl! {}\n\n        type Output = T;\n        type Residual = Option<Infallible>;\n\n        fn from_output(output: Self::Output) -> Self {\n            Some(output)\n        }\n\n        fn from_residual(residual: Self::Residual) -> Self {\n            match residual {\n                None => None,\n                #[allow(unreachable_patterns)]\n                Some(_) => unreachable!(),\n            }\n        }\n\n        fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {\n            match self {\n                Some(c) => Continue(c),\n                None => Break(None),\n            }\n        }\n    }\n\n    impl<T, E> Try for Result<T, E> {\n        private_impl! {}\n\n        type Output = T;\n        type Residual = Result<Infallible, E>;\n\n        fn from_output(output: Self::Output) -> Self {\n            Ok(output)\n        }\n\n        fn from_residual(residual: Self::Residual) -> Self {\n            match residual {\n                Err(e) => Err(e),\n                #[allow(unreachable_patterns)]\n                Ok(_) => unreachable!(),\n            }\n        }\n\n        fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {\n            match self {\n                Ok(c) => Continue(c),\n                Err(e) => Break(Err(e)),\n            }\n        }\n    }\n\n    impl<T, E> Try for Poll<Result<T, E>> {\n        private_impl! {}\n\n        type Output = Poll<T>;\n        type Residual = Result<Infallible, E>;\n\n        fn from_output(output: Self::Output) -> Self {\n            output.map(Ok)\n        }\n\n        fn from_residual(residual: Self::Residual) -> Self {\n            match residual {\n                Err(e) => Poll::Ready(Err(e)),\n                #[allow(unreachable_patterns)]\n                Ok(_) => unreachable!(),\n            }\n        }\n\n        fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {\n            match self {\n                Poll::Pending => Continue(Poll::Pending),\n                Poll::Ready(Ok(c)) => Continue(Poll::Ready(c)),\n                Poll::Ready(Err(e)) => Break(Err(e)),\n            }\n        }\n    }\n\n    impl<T, E> Try for Poll<Option<Result<T, E>>> {\n        private_impl! {}\n\n        type Output = Poll<Option<T>>;\n        type Residual = Result<Infallible, E>;\n\n        fn from_output(output: Self::Output) -> Self {\n            match output {\n                Poll::Ready(o) => Poll::Ready(o.map(Ok)),\n                Poll::Pending => Poll::Pending,\n            }\n        }\n\n        fn from_residual(residual: Self::Residual) -> Self {\n            match residual {\n                Err(e) => Poll::Ready(Some(Err(e))),\n                #[allow(unreachable_patterns)]\n                Ok(_) => unreachable!(),\n            }\n        }\n\n        fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {\n            match self {\n                Poll::Pending => Continue(Poll::Pending),\n                Poll::Ready(None) => Continue(Poll::Ready(None)),\n                Poll::Ready(Some(Ok(c))) => Continue(Poll::Ready(Some(c))),\n                Poll::Ready(Some(Err(e))) => Break(Err(e)),\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/iter/multizip.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\n/// `MultiZip` is an iterator that zips up a tuple of parallel iterators to\n/// produce tuples of their items.\n///\n/// It is created by calling `into_par_iter()` on a tuple of types that\n/// implement `IntoParallelIterator`, or `par_iter()`/`par_iter_mut()` with\n/// types that are iterable by reference.\n///\n/// The implementation currently support tuples up to length 12.\n///\n/// # Examples\n///\n/// ```\n/// use rayon::prelude::*;\n///\n/// // This will iterate `r` by mutable reference, like `par_iter_mut()`, while\n/// // ranges are all iterated by value like `into_par_iter()`.\n/// // Note that the zipped iterator is only as long as the shortest input.\n/// let mut r = vec![0; 3];\n/// (&mut r, 1..10, 10..100, 100..1000).into_par_iter()\n///     .for_each(|(r, x, y, z)| *r = x * y + z);\n///\n/// assert_eq!(&r, &[1 * 10 + 100, 2 * 11 + 101, 3 * 12 + 102]);\n/// ```\n///\n/// For a group that should all be iterated by reference, you can use a tuple reference.\n///\n/// ```\n/// use rayon::prelude::*;\n///\n/// let xs: Vec<_> = (1..10).collect();\n/// let ys: Vec<_> = (10..100).collect();\n/// let zs: Vec<_> = (100..1000).collect();\n///\n/// // Reference each input separately with `IntoParallelIterator`:\n/// let r1: Vec<_> = (&xs, &ys, &zs).into_par_iter()\n///     .map(|(x, y, z)| x * y + z)\n///     .collect();\n///\n/// // Reference them all together with `IntoParallelRefIterator`:\n/// let r2: Vec<_> = (xs, ys, zs).par_iter()\n///     .map(|(x, y, z)| x * y + z)\n///     .collect();\n///\n/// assert_eq!(r1, r2);\n/// ```\n///\n/// Mutable references to a tuple will work similarly.\n///\n/// ```\n/// use rayon::prelude::*;\n///\n/// let mut xs: Vec<_> = (1..4).collect();\n/// let mut ys: Vec<_> = (-4..-1).collect();\n/// let mut zs = vec![0; 3];\n///\n/// // Mutably reference each input separately with `IntoParallelIterator`:\n/// (&mut xs, &mut ys, &mut zs).into_par_iter().for_each(|(x, y, z)| {\n///     *z += *x + *y;\n///     std::mem::swap(x, y);\n/// });\n///\n/// assert_eq!(xs, (vec![-4, -3, -2]));\n/// assert_eq!(ys, (vec![1, 2, 3]));\n/// assert_eq!(zs, (vec![-3, -1, 1]));\n///\n/// // Mutably reference them all together with `IntoParallelRefMutIterator`:\n/// let mut tuple = (xs, ys, zs);\n/// tuple.par_iter_mut().for_each(|(x, y, z)| {\n///     *z += *x + *y;\n///     std::mem::swap(x, y);\n/// });\n///\n/// assert_eq!(tuple, (vec![1, 2, 3], vec![-4, -3, -2], vec![-6, -2, 2]));\n/// ```\n#[derive(Debug, Clone)]\npub struct MultiZip<T> {\n    tuple: T,\n}\n\n// These macros greedily consume 4 or 2 items first to achieve log2 nesting depth.\n// For example, 5 => 4,1 => (2,2),1.\n//\n// The tuples go up to 12, so we might want to greedily consume 8 too, but\n// the depth works out the same if we let that expand on the right:\n//      9 => 4,5 => (2,2),(4,1) => (2,2),((2,2),1)\n//     12 => 4,8 => (2,2),(4,4) => (2,2),((2,2),(2,2))\n//\n// But if we ever increase to 13, we would want to split 8,5 rather than 4,9.\n\nmacro_rules! reduce {\n    ($a:expr, $b:expr, $c:expr, $d:expr, $( $x:expr ),+ => $fn:path) => {\n        reduce!(reduce!($a, $b, $c, $d => $fn),\n                reduce!($( $x ),+ => $fn)\n                => $fn)\n    };\n    ($a:expr, $b:expr, $( $x:expr ),+ => $fn:path) => {\n        reduce!(reduce!($a, $b => $fn),\n                reduce!($( $x ),+ => $fn)\n                => $fn)\n    };\n    ($a:expr, $b:expr => $fn:path) => { $fn($a, $b) };\n    ($a:expr => $fn:path) => { $a };\n}\n\nmacro_rules! nest {\n    ($A:tt, $B:tt, $C:tt, $D:tt, $( $X:tt ),+) => {\n        (nest!($A, $B, $C, $D), nest!($( $X ),+))\n    };\n    ($A:tt, $B:tt, $( $X:tt ),+) => {\n        (($A, $B), nest!($( $X ),+))\n    };\n    ($A:tt, $B:tt) => { ($A, $B) };\n    ($A:tt) => { $A };\n}\n\nmacro_rules! flatten {\n    ($( $T:ident ),+) => {{\n        #[allow(non_snake_case)]\n        fn flatten<$( $T ),+>(nest!($( $T ),+) : nest!($( $T ),+)) -> ($( $T, )+) {\n            ($( $T, )+)\n        }\n        flatten\n    }};\n}\n\nmacro_rules! multizip_impls {\n    ($(\n        $Tuple:ident {\n            $(($idx:tt) -> $T:ident)+\n        }\n    )+) => {\n        $(\n            impl<$( $T, )+> IntoParallelIterator for ($( $T, )+)\n            where\n                $(\n                    $T: IntoParallelIterator<Iter: IndexedParallelIterator>,\n                )+\n            {\n                type Item = ($( $T::Item, )+);\n                type Iter = MultiZip<($( $T::Iter, )+)>;\n\n                fn into_par_iter(self) -> Self::Iter {\n                    MultiZip {\n                        tuple: ( $( self.$idx.into_par_iter(), )+ ),\n                    }\n                }\n            }\n\n            impl<'a, $( $T, )+> IntoParallelIterator for &'a ($( $T, )+)\n            where\n                $(\n                    $T: IntoParallelRefIterator<'a, Iter: IndexedParallelIterator>,\n                )+\n            {\n                type Item = ($( $T::Item, )+);\n                type Iter = MultiZip<($( $T::Iter, )+)>;\n\n                fn into_par_iter(self) -> Self::Iter {\n                    MultiZip {\n                        tuple: ( $( self.$idx.par_iter(), )+ ),\n                    }\n                }\n            }\n\n            impl<'a, $( $T, )+> IntoParallelIterator for &'a mut ($( $T, )+)\n            where\n                $(\n                    $T: IntoParallelRefMutIterator<'a, Iter: IndexedParallelIterator>,\n                )+\n            {\n                type Item = ($( $T::Item, )+);\n                type Iter = MultiZip<($( $T::Iter, )+)>;\n\n                fn into_par_iter(self) -> Self::Iter {\n                    MultiZip {\n                        tuple: ( $( self.$idx.par_iter_mut(), )+ ),\n                    }\n                }\n            }\n\n            impl<$( $T, )+> ParallelIterator for MultiZip<($( $T, )+)>\n            where\n                $( $T: IndexedParallelIterator, )+\n            {\n                type Item = ($( $T::Item, )+);\n\n                fn drive_unindexed<CONSUMER>(self, consumer: CONSUMER) -> CONSUMER::Result\n                where\n                    CONSUMER: UnindexedConsumer<Self::Item>,\n                {\n                    self.drive(consumer)\n                }\n\n                fn opt_len(&self) -> Option<usize> {\n                    Some(self.len())\n                }\n            }\n\n            impl<$( $T, )+> IndexedParallelIterator for MultiZip<($( $T, )+)>\n            where\n                $( $T: IndexedParallelIterator, )+\n            {\n                fn drive<CONSUMER>(self, consumer: CONSUMER) -> CONSUMER::Result\n                where\n                    CONSUMER: Consumer<Self::Item>,\n                {\n                    reduce!($( self.tuple.$idx ),+ => IndexedParallelIterator::zip)\n                        .map(flatten!($( $T ),+))\n                        .drive(consumer)\n                }\n\n                fn len(&self) -> usize {\n                    reduce!($( self.tuple.$idx.len() ),+ => Ord::min)\n                }\n\n                fn with_producer<CB>(self, callback: CB) -> CB::Output\n                where\n                    CB: ProducerCallback<Self::Item>,\n                {\n                    reduce!($( self.tuple.$idx ),+ => IndexedParallelIterator::zip)\n                        .map(flatten!($( $T ),+))\n                        .with_producer(callback)\n                }\n            }\n        )+\n    }\n}\n\nmultizip_impls! {\n    Tuple1 {\n        (0) -> A\n    }\n    Tuple2 {\n        (0) -> A\n        (1) -> B\n    }\n    Tuple3 {\n        (0) -> A\n        (1) -> B\n        (2) -> C\n    }\n    Tuple4 {\n        (0) -> A\n        (1) -> B\n        (2) -> C\n        (3) -> D\n    }\n    Tuple5 {\n        (0) -> A\n        (1) -> B\n        (2) -> C\n        (3) -> D\n        (4) -> E\n    }\n    Tuple6 {\n        (0) -> A\n        (1) -> B\n        (2) -> C\n        (3) -> D\n        (4) -> E\n        (5) -> F\n    }\n    Tuple7 {\n        (0) -> A\n        (1) -> B\n        (2) -> C\n        (3) -> D\n        (4) -> E\n        (5) -> F\n        (6) -> G\n    }\n    Tuple8 {\n        (0) -> A\n        (1) -> B\n        (2) -> C\n        (3) -> D\n        (4) -> E\n        (5) -> F\n        (6) -> G\n        (7) -> H\n    }\n    Tuple9 {\n        (0) -> A\n        (1) -> B\n        (2) -> C\n        (3) -> D\n        (4) -> E\n        (5) -> F\n        (6) -> G\n        (7) -> H\n        (8) -> I\n    }\n    Tuple10 {\n        (0) -> A\n        (1) -> B\n        (2) -> C\n        (3) -> D\n        (4) -> E\n        (5) -> F\n        (6) -> G\n        (7) -> H\n        (8) -> I\n        (9) -> J\n    }\n    Tuple11 {\n        (0) -> A\n        (1) -> B\n        (2) -> C\n        (3) -> D\n        (4) -> E\n        (5) -> F\n        (6) -> G\n        (7) -> H\n        (8) -> I\n        (9) -> J\n        (10) -> K\n    }\n    Tuple12 {\n        (0) -> A\n        (1) -> B\n        (2) -> C\n        (3) -> D\n        (4) -> E\n        (5) -> F\n        (6) -> G\n        (7) -> H\n        (8) -> I\n        (9) -> J\n        (10) -> K\n        (11) -> L\n    }\n}\n"
  },
  {
    "path": "src/iter/noop.rs",
    "content": "use super::plumbing::*;\n\npub(super) struct NoopConsumer;\n\nimpl<T> Consumer<T> for NoopConsumer {\n    type Folder = NoopConsumer;\n    type Reducer = NoopReducer;\n    type Result = ();\n\n    fn split_at(self, _index: usize) -> (Self, Self, NoopReducer) {\n        (NoopConsumer, NoopConsumer, NoopReducer)\n    }\n\n    fn into_folder(self) -> Self {\n        self\n    }\n\n    fn full(&self) -> bool {\n        false\n    }\n}\n\nimpl<T> Folder<T> for NoopConsumer {\n    type Result = ();\n\n    fn consume(self, _item: T) -> Self {\n        self\n    }\n\n    fn consume_iter<I>(self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = T>,\n    {\n        iter.into_iter().for_each(drop);\n        self\n    }\n\n    fn complete(self) {}\n\n    fn full(&self) -> bool {\n        false\n    }\n}\n\nimpl<T> UnindexedConsumer<T> for NoopConsumer {\n    fn split_off_left(&self) -> Self {\n        NoopConsumer\n    }\n\n    fn to_reducer(&self) -> NoopReducer {\n        NoopReducer\n    }\n}\n\npub(super) struct NoopReducer;\n\nimpl Reducer<()> for NoopReducer {\n    fn reduce(self, _left: (), _right: ()) {}\n}\n"
  },
  {
    "path": "src/iter/once.rs",
    "content": "use crate::iter::plumbing::*;\nuse crate::iter::*;\n\n/// Creates a parallel iterator that produces an element exactly once.\n///\n/// This admits no parallelism on its own, but it could be chained to existing\n/// parallel iterators to extend their contents, or otherwise used for any code\n/// that deals with generic parallel iterators.\n///\n/// # Examples\n///\n/// ```\n/// use rayon::prelude::*;\n/// use rayon::iter::once;\n///\n/// let pi = (0..1234).into_par_iter()\n///     .chain(once(-1))\n///     .chain(1234..10_000);\n///\n/// assert_eq!(pi.clone().count(), 10_001);\n/// assert_eq!(pi.clone().filter(|&x| x < 0).count(), 1);\n/// assert_eq!(pi.position_any(|x| x < 0), Some(1234));\n/// ```\npub fn once<T: Send>(item: T) -> Once<T> {\n    Once { item }\n}\n\n/// Iterator adaptor for [the `once()` function].\n///\n/// [the `once()` function]: once()\n#[derive(Clone, Debug)]\npub struct Once<T> {\n    item: T,\n}\n\nimpl<T: Send> ParallelIterator for Once<T> {\n    type Item = T;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        self.drive(consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(1)\n    }\n}\n\nimpl<T: Send> IndexedParallelIterator for Once<T> {\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        consumer.into_folder().consume(self.item).complete()\n    }\n\n    fn len(&self) -> usize {\n        1\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        // Let `OptionProducer` handle it.\n        Some(self.item).into_par_iter().with_producer(callback)\n    }\n}\n"
  },
  {
    "path": "src/iter/panic_fuse.rs",
    "content": "use super::plumbing::*;\nuse super::*;\nuse std::sync::atomic::{AtomicBool, Ordering};\nuse std::thread;\n\n/// `PanicFuse` is an adaptor that wraps an iterator with a fuse in case\n/// of panics, to halt all threads as soon as possible.\n///\n/// This struct is created by the [`panic_fuse()`] method on [`ParallelIterator`]\n///\n/// [`panic_fuse()`]: ParallelIterator::panic_fuse()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\npub struct PanicFuse<I> {\n    base: I,\n}\n\n/// Helper that sets a bool to `true` if dropped while unwinding.\n#[derive(Clone)]\nstruct Fuse<'a>(&'a AtomicBool);\n\nimpl<'a> Drop for Fuse<'a> {\n    #[inline]\n    fn drop(&mut self) {\n        if thread::panicking() {\n            self.0.store(true, Ordering::Relaxed);\n        }\n    }\n}\n\nimpl<'a> Fuse<'a> {\n    #[inline]\n    fn panicked(&self) -> bool {\n        self.0.load(Ordering::Relaxed)\n    }\n}\n\nimpl<I> PanicFuse<I> {\n    /// Creates a new `PanicFuse` iterator.\n    pub(super) fn new(base: I) -> PanicFuse<I> {\n        PanicFuse { base }\n    }\n}\n\nimpl<I> ParallelIterator for PanicFuse<I>\nwhere\n    I: ParallelIterator,\n{\n    type Item = I::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let panicked = AtomicBool::new(false);\n        let consumer1 = PanicFuseConsumer {\n            base: consumer,\n            fuse: Fuse(&panicked),\n        };\n        self.base.drive_unindexed(consumer1)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        self.base.opt_len()\n    }\n}\n\nimpl<I> IndexedParallelIterator for PanicFuse<I>\nwhere\n    I: IndexedParallelIterator,\n{\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        let panicked = AtomicBool::new(false);\n        let consumer1 = PanicFuseConsumer {\n            base: consumer,\n            fuse: Fuse(&panicked),\n        };\n        self.base.drive(consumer1)\n    }\n\n    fn len(&self) -> usize {\n        self.base.len()\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        return self.base.with_producer(Callback { callback });\n\n        struct Callback<CB> {\n            callback: CB,\n        }\n\n        impl<T, CB> ProducerCallback<T> for Callback<CB>\n        where\n            CB: ProducerCallback<T>,\n        {\n            type Output = CB::Output;\n\n            fn callback<P>(self, base: P) -> CB::Output\n            where\n                P: Producer<Item = T>,\n            {\n                let panicked = AtomicBool::new(false);\n                let producer = PanicFuseProducer {\n                    base,\n                    fuse: Fuse(&panicked),\n                };\n                self.callback.callback(producer)\n            }\n        }\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Producer implementation\n\nstruct PanicFuseProducer<'a, P> {\n    base: P,\n    fuse: Fuse<'a>,\n}\n\nimpl<'a, P> Producer for PanicFuseProducer<'a, P>\nwhere\n    P: Producer,\n{\n    type Item = P::Item;\n    type IntoIter = PanicFuseIter<'a, P::IntoIter>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        PanicFuseIter {\n            base: self.base.into_iter(),\n            fuse: self.fuse,\n        }\n    }\n\n    fn min_len(&self) -> usize {\n        self.base.min_len()\n    }\n    fn max_len(&self) -> usize {\n        self.base.max_len()\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let (left, right) = self.base.split_at(index);\n        (\n            PanicFuseProducer {\n                base: left,\n                fuse: self.fuse.clone(),\n            },\n            PanicFuseProducer {\n                base: right,\n                fuse: self.fuse,\n            },\n        )\n    }\n\n    fn fold_with<G>(self, folder: G) -> G\n    where\n        G: Folder<Self::Item>,\n    {\n        let folder1 = PanicFuseFolder {\n            base: folder,\n            fuse: self.fuse,\n        };\n        self.base.fold_with(folder1).base\n    }\n}\n\nstruct PanicFuseIter<'a, I> {\n    base: I,\n    fuse: Fuse<'a>,\n}\n\nimpl<'a, I> Iterator for PanicFuseIter<'a, I>\nwhere\n    I: Iterator,\n{\n    type Item = I::Item;\n\n    fn next(&mut self) -> Option<Self::Item> {\n        if self.fuse.panicked() {\n            None\n        } else {\n            self.base.next()\n        }\n    }\n\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        self.base.size_hint()\n    }\n}\n\nimpl<'a, I> DoubleEndedIterator for PanicFuseIter<'a, I>\nwhere\n    I: DoubleEndedIterator,\n{\n    fn next_back(&mut self) -> Option<Self::Item> {\n        if self.fuse.panicked() {\n            None\n        } else {\n            self.base.next_back()\n        }\n    }\n}\n\nimpl<'a, I> ExactSizeIterator for PanicFuseIter<'a, I>\nwhere\n    I: ExactSizeIterator,\n{\n    fn len(&self) -> usize {\n        self.base.len()\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Consumer implementation\n\nstruct PanicFuseConsumer<'a, C> {\n    base: C,\n    fuse: Fuse<'a>,\n}\n\nimpl<'a, T, C> Consumer<T> for PanicFuseConsumer<'a, C>\nwhere\n    C: Consumer<T>,\n{\n    type Folder = PanicFuseFolder<'a, C::Folder>;\n    type Reducer = PanicFuseReducer<'a, C::Reducer>;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            PanicFuseConsumer {\n                base: left,\n                fuse: self.fuse.clone(),\n            },\n            PanicFuseConsumer {\n                base: right,\n                fuse: self.fuse.clone(),\n            },\n            PanicFuseReducer {\n                base: reducer,\n                _fuse: self.fuse,\n            },\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        PanicFuseFolder {\n            base: self.base.into_folder(),\n            fuse: self.fuse,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.fuse.panicked() || self.base.full()\n    }\n}\n\nimpl<'a, T, C> UnindexedConsumer<T> for PanicFuseConsumer<'a, C>\nwhere\n    C: UnindexedConsumer<T>,\n{\n    fn split_off_left(&self) -> Self {\n        PanicFuseConsumer {\n            base: self.base.split_off_left(),\n            fuse: self.fuse.clone(),\n        }\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        PanicFuseReducer {\n            base: self.base.to_reducer(),\n            _fuse: self.fuse.clone(),\n        }\n    }\n}\n\nstruct PanicFuseFolder<'a, C> {\n    base: C,\n    fuse: Fuse<'a>,\n}\n\nimpl<'a, T, C> Folder<T> for PanicFuseFolder<'a, C>\nwhere\n    C: Folder<T>,\n{\n    type Result = C::Result;\n\n    fn consume(mut self, item: T) -> Self {\n        self.base = self.base.consume(item);\n        self\n    }\n\n    fn consume_iter<I>(mut self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = T>,\n    {\n        fn cool<'a, T>(fuse: &'a Fuse<'_>) -> impl Fn(&T) -> bool + 'a {\n            move |_| !fuse.panicked()\n        }\n\n        self.base = {\n            let fuse = &self.fuse;\n            let iter = iter.into_iter().take_while(cool(fuse));\n            self.base.consume_iter(iter)\n        };\n        self\n    }\n\n    fn complete(self) -> C::Result {\n        self.base.complete()\n    }\n\n    fn full(&self) -> bool {\n        self.fuse.panicked() || self.base.full()\n    }\n}\n\nstruct PanicFuseReducer<'a, C> {\n    base: C,\n    _fuse: Fuse<'a>,\n}\n\nimpl<'a, T, C> Reducer<T> for PanicFuseReducer<'a, C>\nwhere\n    C: Reducer<T>,\n{\n    fn reduce(self, left: T, right: T) -> T {\n        self.base.reduce(left, right)\n    }\n}\n"
  },
  {
    "path": "src/iter/par_bridge.rs",
    "content": "#[cfg(not(feature = \"web_spin_lock\"))]\nuse std::sync::Mutex;\n\n#[cfg(feature = \"web_spin_lock\")]\nuse wasm_sync::Mutex;\n\nuse std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};\n\nuse crate::iter::plumbing::{bridge_unindexed, Folder, UnindexedConsumer, UnindexedProducer};\nuse crate::iter::ParallelIterator;\nuse crate::{current_num_threads, current_thread_index};\n\n/// Conversion trait to convert an `Iterator` to a `ParallelIterator`.\n///\n/// This creates a \"bridge\" from a sequential iterator to a parallel one, by distributing its items\n/// across the Rayon thread pool. This has the advantage of being able to parallelize just about\n/// anything, but the resulting `ParallelIterator` can be less efficient than if you started with\n/// `par_iter` instead. However, it can still be useful for iterators that are difficult to\n/// parallelize by other means, like channels or file or network I/O.\n///\n/// Iterator items are pulled by `next()` one at a time, synchronized from each thread that is\n/// ready for work, so this may become a bottleneck if the serial iterator can't keep up with the\n/// parallel demand. The items are not buffered by `IterBridge`, so it's fine to use this with\n/// large or even unbounded iterators.\n///\n/// The resulting iterator is not guaranteed to keep the order of the original iterator.\n///\n/// # Examples\n///\n/// To use this trait, take an existing `Iterator` and call `par_bridge` on it. After that, you can\n/// use any of the `ParallelIterator` methods:\n///\n/// ```\n/// use rayon::iter::ParallelBridge;\n/// use rayon::prelude::ParallelIterator;\n/// use std::sync::mpsc::channel;\n///\n/// let rx = {\n///     let (tx, rx) = channel();\n///\n///     tx.send(\"one!\");\n///     tx.send(\"two!\");\n///     tx.send(\"three!\");\n///\n///     rx\n/// };\n///\n/// let mut output: Vec<&'static str> = rx.into_iter().par_bridge().collect();\n/// output.sort_unstable();\n///\n/// assert_eq!(&*output, &[\"one!\", \"three!\", \"two!\"]);\n/// ```\npub trait ParallelBridge: Sized {\n    /// Creates a bridge from this type to a `ParallelIterator`.\n    fn par_bridge(self) -> IterBridge<Self>;\n}\n\nimpl<T> ParallelBridge for T\nwhere\n    T: Iterator<Item: Send> + Send,\n{\n    fn par_bridge(self) -> IterBridge<Self> {\n        IterBridge { iter: self }\n    }\n}\n\n/// `IterBridge` is a parallel iterator that wraps a sequential iterator.\n///\n/// This type is created when using the `par_bridge` method on `ParallelBridge`. See the\n/// [`ParallelBridge`] documentation for details.\n#[derive(Debug, Clone)]\npub struct IterBridge<Iter> {\n    iter: Iter,\n}\n\nimpl<Iter> ParallelIterator for IterBridge<Iter>\nwhere\n    Iter: Iterator<Item: Send> + Send,\n{\n    type Item = Iter::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let num_threads = current_num_threads();\n        let threads_started: Vec<_> = (0..num_threads).map(|_| AtomicBool::new(false)).collect();\n\n        bridge_unindexed(\n            &IterParallelProducer {\n                split_count: AtomicUsize::new(num_threads),\n                iter: Mutex::new(self.iter.fuse()),\n                threads_started: &threads_started,\n            },\n            consumer,\n        )\n    }\n}\n\nstruct IterParallelProducer<'a, Iter> {\n    split_count: AtomicUsize,\n    iter: Mutex<std::iter::Fuse<Iter>>,\n    threads_started: &'a [AtomicBool],\n}\n\nimpl<Iter: Iterator + Send> UnindexedProducer for &IterParallelProducer<'_, Iter> {\n    type Item = Iter::Item;\n\n    fn split(self) -> (Self, Option<Self>) {\n        // Check if the iterator is exhausted\n        let update = self\n            .split_count\n            .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |c| c.checked_sub(1));\n        (self, update.is_ok().then_some(self))\n    }\n\n    fn fold_with<F>(self, mut folder: F) -> F\n    where\n        F: Folder<Self::Item>,\n    {\n        // Guard against work-stealing-induced recursion, in case `Iter::next()`\n        // calls rayon internally, so we don't deadlock our mutex. We might also\n        // be recursing via `folder` methods, which doesn't present a mutex hazard,\n        // but it's lower overhead for us to just check this once, rather than\n        // updating additional shared state on every mutex lock/unlock.\n        // (If this isn't a rayon thread, then there's no work-stealing anyway...)\n        if let Some(i) = current_thread_index() {\n            // Note: If the number of threads in the pool ever grows dynamically, then\n            // we'll end up sharing flags and may falsely detect recursion -- that's\n            // still fine for overall correctness, just not optimal for parallelism.\n            let thread_started = &self.threads_started[i % self.threads_started.len()];\n            if thread_started.swap(true, Ordering::Relaxed) {\n                // We can't make progress with a nested mutex, so just return and let\n                // the outermost loop continue with the rest of the iterator items.\n                return folder;\n            }\n        }\n\n        loop {\n            if let Ok(mut iter) = self.iter.lock() {\n                if let Some(it) = iter.next() {\n                    drop(iter);\n                    folder = folder.consume(it);\n                    if folder.full() {\n                        return folder;\n                    }\n                } else {\n                    return folder;\n                }\n            } else {\n                // any panics from other threads will have been caught by the pool,\n                // and will be re-thrown when joined - just exit\n                return folder;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/iter/plumbing/README.md",
    "content": "# Parallel Iterators\n\nThese are some notes on the design of the parallel iterator traits.\nThis file does not describe how to **use** parallel iterators.\n\n## The challenge\n\nParallel iterators are more complicated than sequential iterators.\nThe reason is that they have to be able to split themselves up and\noperate in parallel across the two halves.\n\nThe current design for parallel iterators has two distinct modes in\nwhich they can be used; as we will see, not all iterators support both\nmodes (which is why there are two):\n\n- **Pull mode** (the `Producer` and `UnindexedProducer` traits): in this mode,\n  the iterator is asked to produce the next item using a call to `next`. This\n  is basically like a normal iterator, but with a twist: you can split the\n  iterator in half to produce disjoint items in separate threads.\n  - in the `Producer` trait, splitting is done with `split_at`, which accepts\n    an index where the split should be performed. Only indexed iterators can\n    work in this mode, as they know exactly how much data they will produce,\n    and how to locate the requested index.\n  - in the `UnindexedProducer` trait, splitting is done with `split`, which\n    simply requests that the producer divide itself *approximately* in half.\n    This is useful when the exact length and/or layout is unknown, as with\n    `String` characters, or when the length might exceed `usize`, as with\n    `Range<u64>` on 32-bit platforms.\n    - In theory, any `Producer` could act unindexed, but we don't currently\n      use that possibility.  When you know the exact length, a `split` can\n      simply be implemented as `split_at(length/2)`.\n- **Push mode** (the `Consumer` and `UnindexedConsumer` traits): in\n  this mode, the iterator instead is *given* each item in turn, which\n  is then processed. This is the opposite of a normal iterator. It's\n  more like a `for_each` call: each time a new item is produced, the\n  `consume` method is called with that item. (The traits themselves are\n  a bit more complex, as they support state that can be threaded\n  through and ultimately reduced.) Like producers, there are two\n  variants of consumers which differ in how the split is performed:\n  - in the `Consumer` trait, splitting is done with `split_at`, which\n    accepts an index where the split should be performed. All\n    iterators can work in this mode. The resulting halves thus have an\n    idea about how much data they expect to consume.\n  - in the `UnindexedConsumer` trait, splitting is done with\n    `split_off_left`.  There is no index: the resulting halves must be\n    prepared to process any amount of data, and they don't know where that\n    data falls in the overall stream.\n    - Not all consumers can operate in this mode. It works for\n      `for_each` and `reduce`, for example, but it does not work for\n      `collect_into_vec`, since in that case the position of each item is\n      important for knowing where it ends up in the target collection.\n\n## How iterator execution proceeds\n\nWe'll walk through this example iterator chain to start. This chain\ndemonstrates more-or-less the full complexity of what can happen.\n\n```rust\nvec1.par_iter()\n    .zip(vec2.par_iter())\n    .flat_map(some_function)\n    .for_each(some_other_function)\n```\n\nTo handle an iterator chain, we start by creating consumers. This\nworks from the end. So in this case, the call to `for_each` is the\nfinal step, so it will create a `ForEachConsumer` that, given an item,\njust calls `some_other_function` with that item. (`ForEachConsumer` is\na very simple consumer because it doesn't need to thread any state\nbetween items at all.)\n\nNow, the `for_each` call will pass this consumer to the base iterator,\nwhich is the `flat_map`. It will do this by calling the `drive_unindexed`\nmethod on the `ParallelIterator` trait. `drive_unindexed` basically\nsays \"produce items for this iterator and feed them to this consumer\";\nit only works for unindexed consumers.\n\n(As an aside, it is interesting that only some consumers can work in\nunindexed mode, but all producers can *drive* an unindexed consumer.\nIn contrast, only some producers can drive an *indexed* consumer, but\nall consumers can be supplied indexes. Isn't variance neat.)\n\nAs it happens, `FlatMap` only works with unindexed consumers anyway.\nThis is because flat-map basically has no idea how many items it will\nproduce. If you ask flat-map to produce the 22nd item, it can't do it,\nat least not without some intermediate state. It doesn't know whether\nprocessing the first item will create 1 item, 3 items, or 100;\ntherefore, to produce an arbitrary item, it would basically just have\nto start at the beginning and execute sequentially, which is not what\nwe want. But for unindexed consumers, this doesn't matter, since they\ndon't need to know how much data they will get.\n\nTherefore, `FlatMap` can wrap the `ForEachConsumer` with a\n`FlatMapConsumer` that feeds to it. This `FlatMapConsumer` will be\ngiven one item. It will then invoke `some_function` to get a parallel\niterator out. It will then ask this new parallel iterator to drive the\n`ForEachConsumer`. The `drive_unindexed` method on `flat_map` can then\npass the `FlatMapConsumer` up the chain to the previous item, which is\n`zip`. At this point, something interesting happens.\n\n## Switching from push to pull mode\n\nIf you think about `zip`, it can't really be implemented as a\nconsumer, at least not without an intermediate thread and some\nchannels or something (or maybe coroutines). The problem is that it\nhas to walk two iterators *in lockstep*. Basically, it can't call two\n`drive` methods simultaneously, it can only call one at a time. So at\nthis point, the `zip` iterator needs to switch from *push mode* into\n*pull mode*.\n\nYou'll note that `Zip` is only usable if its inputs implement\n`IndexedParallelIterator`, meaning that they can produce data starting\nat random points in the stream. This need to switch to push mode is\nexactly why. If we want to split a zip iterator at position 22, we\nneed to be able to start zipping items from index 22 right away,\nwithout having to start from index 0.\n\nAnyway, so at this point, the `drive_unindexed` method for `Zip` stops\ncreating consumers. Instead, it creates a *producer*, a `ZipProducer`,\nto be exact, and calls the `bridge` function in the `internals`\nmodule. Creating a `ZipProducer` will in turn create producers for\nthe two iterators being zipped. This is possible because they both\nimplement `IndexedParallelIterator`.\n\nThe `bridge` function will then connect the consumer, which is\nhandling the `flat_map` and `for_each`, with the producer, which is\nhandling the `zip` and its predecessors. It will split down until the\nchunks seem reasonably small, then pull items from the producer and\nfeed them to the consumer.\n\n## The base case\n\nThe other time that `bridge` gets used is when we bottom out in an\nindexed producer, such as a slice or range.  There is also a\n`bridge_unindexed` equivalent for - you guessed it - unindexed producers,\nsuch as string characters.\n\n<a name=\"producer-callback\">\n\n## What on earth is `ProducerCallback`?\n\nWe saw that when you call a parallel action method like\n`par_iter.reduce()`, that will create a \"reducing\" consumer and then\ninvoke `par_iter.drive_unindexed()` (or `par_iter.drive()`) as\nappropriate. This may create yet more consumers as we proceed up the\nparallel iterator chain. But at some point we're going to get to the\nstart of the chain, or to a parallel iterator (like `zip()`) that has\nto coordinate multiple inputs. At that point, we need to start\nconverting parallel iterators into producers.\n\nThe way we do this is by invoking the method `with_producer()`, defined on\n`IndexedParallelIterator`. This is a callback scheme. In an ideal world,\nit would work like this:\n\n```rust\nbase_iter.with_producer(|base_producer| {\n    // here, `base_producer` is the producer for `base_iter`\n});\n```\n\nIn that case, we could implement a combinator like `map()` by getting\nthe producer for the base iterator, wrapping it to make our own\n`MapProducer`, and then passing that to the callback. Something like\nthis:\n\n```rust\nstruct MapProducer<'f, P, F: 'f> {\n    base: P,\n    map_op: &'f F,\n}\n\nimpl<I, F> IndexedParallelIterator for Map<I, F>\n    where I: IndexedParallelIterator,\n          F: MapOp<I::Item>,\n{\n    fn with_producer<CB>(self, callback: CB) -> CB::Output {\n        let map_op = &self.map_op;\n        self.base_iter.with_producer(|base_producer| {\n            // Here `producer` is the producer for `self.base_iter`.\n            // Wrap that to make a `MapProducer`\n            let map_producer = MapProducer {\n                base: base_producer,\n                map_op: map_op\n            };\n\n            // invoke the callback with the wrapped version\n            callback(map_producer)\n        });\n    }\n});\n```\n\nThis example demonstrates some of the power of the callback scheme.\nIt winds up being a very flexible setup. For one thing, it means we\ncan take ownership of `par_iter`; we can then in turn give ownership\naway of its bits and pieces into the producer (this is very useful if\nthe iterator owns an `&mut` slice, for example), or create shared\nreferences and put *those* in the producer. In the case of map, for\nexample, the parallel iterator owns the `map_op`, and we borrow\nreferences to it which we then put into the `MapProducer` (this means\nthe `MapProducer` can easily split itself and share those references).\nThe `with_producer` method can also create resources that are needed\nduring the parallel execution, since the producer does not have to be\nreturned.\n\nUnfortunately there is a catch. We can't actually use closures the way\nI showed you. To see why, think about the type that `map_producer`\nwould have to have. If we were going to write the `with_producer`\nmethod using a closure, it would have to look something like this:\n\n```rust\npub trait IndexedParallelIterator: ParallelIterator {\n    type Producer;\n    fn with_producer<CB, R>(self, callback: CB) -> R\n        where CB: FnOnce(Self::Producer) -> R;\n    ...\n}\n```\n\nNote that we had to add this associated type `Producer` so that\nwe could specify the argument of the callback to be `Self::Producer`.\nNow, imagine trying to write that `MapProducer` impl using this style:\n\n```rust\nimpl<I, F> IndexedParallelIterator for Map<I, F>\n    where I: IndexedParallelIterator,\n          F: MapOp<I::Item>,\n{\n    type MapProducer = MapProducer<'f, P::Producer, F>;\n    //                             ^^ wait, what is this `'f`?\n\n    fn with_producer<CB, R>(self, callback: CB) -> R\n        where CB: FnOnce(Self::Producer) -> R\n    {\n        let map_op = &self.map_op;\n        //  ^^^^^^ `'f` is (conceptually) the lifetime of this reference,\n        //         so it will be different for each call to `with_producer`!\n    }\n}\n```\n\nThis may look familiar to you: it's the same problem that we have\ntrying to define an `Iterable` trait. Basically, the producer type\nneeds to include a lifetime (here, `'f`) that refers to the body of\n`with_producer` and hence is not in scope at the impl level.\n\nIf we had [associated type constructors][1598], we could solve this\nproblem that way. But there is another solution. We can use a\ndedicated callback trait like `ProducerCallback`, instead of `FnOnce`:\n\n[1598]: https://github.com/rust-lang/rfcs/pull/1598\n\n```rust\npub trait ProducerCallback<T> {\n    type Output;\n    fn callback<P>(self, producer: P) -> Self::Output\n        where P: Producer<Item=T>;\n}\n```\n\nUsing this trait, the signature of `with_producer()` looks like this:\n\n```rust\nfn with_producer<CB: ProducerCallback<Self::Item>>(self, callback: CB) -> CB::Output;\n```\n\nNotice that this signature **never has to name the producer type** --\nthere is no associated type `Producer` anymore. This is because the\n`callback()` method is generically over **all** producers `P`.\n\nThe problem is that now the `||` sugar doesn't work anymore. So we\nhave to manually create the callback struct, which is a mite tedious.\nSo our `MapProducer` code looks like this:\n\n```rust\nimpl<I, F> IndexedParallelIterator for Map<I, F>\n    where I: IndexedParallelIterator,\n          F: MapOp<I::Item>,\n{\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n        where CB: ProducerCallback<Self::Item>\n    {\n        return self.base.with_producer(Callback { callback: callback, map_op: self.map_op });\n        //                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n        //                             Manual version of the closure sugar: create an instance\n        //                             of a struct that implements `ProducerCallback`.\n\n        // The struct declaration. Each field is something that need to capture from the\n        // creating scope.\n        struct Callback<CB, F> {\n            callback: CB,\n            map_op: F,\n        }\n\n        // Implement the `ProducerCallback` trait. This is pure boilerplate.\n        impl<T, F, CB> ProducerCallback<T> for Callback<CB, F>\n            where F: MapOp<T>,\n                  CB: ProducerCallback<F::Output>\n        {\n            type Output = CB::Output;\n\n            fn callback<P>(self, base: P) -> CB::Output\n                where P: Producer<Item=T>\n            {\n                // The body of the closure is here:\n                let producer = MapProducer { base: base,\n                                             map_op: &self.map_op };\n                self.callback.callback(producer)\n            }\n        }\n    }\n}\n```\n\nOK, a bit tedious, but it works!\n"
  },
  {
    "path": "src/iter/plumbing/mod.rs",
    "content": "//! Traits and functions used to implement parallel iteration.  These are\n//! low-level details -- users of parallel iterators should not need to\n//! interact with them directly.  See [the `plumbing` README][r] for a general overview.\n//!\n//! [r]: https://github.com/rayon-rs/rayon/blob/main/src/iter/plumbing/README.md\n\nuse crate::join_context;\n\nuse super::IndexedParallelIterator;\n\n/// The `ProducerCallback` trait is a kind of generic closure,\n/// [analogous to `FnOnce`][FnOnce]. See [the corresponding section in\n/// the plumbing README][r] for more details.\n///\n/// [r]: https://github.com/rayon-rs/rayon/blob/main/src/iter/plumbing/README.md#producer-callback\n/// [FnOnce]: std::ops::FnOnce\npub trait ProducerCallback<T> {\n    /// The type of value returned by this callback. Analogous to\n    /// [`Output` from the `FnOnce` trait][Output].\n    ///\n    /// [Output]: std::ops::FnOnce::Output\n    type Output;\n\n    /// Invokes the callback with the given producer as argument. The\n    /// key point of this trait is that this method is generic over\n    /// `P`, and hence implementors must be defined for any producer.\n    fn callback<P>(self, producer: P) -> Self::Output\n    where\n        P: Producer<Item = T>;\n}\n\n/// A `Producer` is effectively a \"splittable `IntoIterator`\". That\n/// is, a producer is a value which can be converted into an iterator\n/// at any time: at that point, it simply produces items on demand,\n/// like any iterator. But what makes a `Producer` special is that,\n/// *before* we convert to an iterator, we can also **split** it at a\n/// particular point using the `split_at` method. This will yield up\n/// two producers, one producing the items before that point, and one\n/// producing the items after that point (these two producers can then\n/// independently be split further, or be converted into iterators).\n/// In Rayon, this splitting is used to divide between threads.\n/// See [the `plumbing` README][r] for further details.\n///\n/// Note that each producer will always produce a fixed number of\n/// items N. However, this number N is not queryable through the API;\n/// the consumer is expected to track it.\n///\n/// NB. You might expect `Producer` to extend the `IntoIterator`\n/// trait.  However, [rust-lang/rust#20671][20671] prevents us from\n/// declaring the DoubleEndedIterator and ExactSizeIterator\n/// constraints on a required IntoIterator trait, so we inline\n/// IntoIterator here until that issue is fixed.\n///\n/// [r]: https://github.com/rayon-rs/rayon/blob/main/src/iter/plumbing/README.md\n/// [20671]: https://github.com/rust-lang/rust/issues/20671\npub trait Producer: Send + Sized {\n    /// The type of item that will be produced by this producer once\n    /// it is converted into an iterator.\n    type Item;\n\n    /// The type of iterator we will become.\n    type IntoIter: Iterator<Item = Self::Item> + DoubleEndedIterator + ExactSizeIterator;\n\n    /// Convert `self` into an iterator; at this point, no more parallel splits\n    /// are possible.\n    fn into_iter(self) -> Self::IntoIter;\n\n    /// The minimum number of items that we will process\n    /// sequentially. Defaults to 1, which means that we will split\n    /// all the way down to a single item. This can be raised higher\n    /// using the [`with_min_len`] method, which will force us to\n    /// create sequential tasks at a larger granularity. Note that\n    /// Rayon automatically normally attempts to adjust the size of\n    /// parallel splits to reduce overhead, so this should not be\n    /// needed.\n    ///\n    /// [`with_min_len`]: super::IndexedParallelIterator::with_min_len()\n    fn min_len(&self) -> usize {\n        1\n    }\n\n    /// The maximum number of items that we will process\n    /// sequentially. Defaults to MAX, which means that we can choose\n    /// not to split at all. This can be lowered using the\n    /// [`with_max_len`] method, which will force us to create more\n    /// parallel tasks. Note that Rayon automatically normally\n    /// attempts to adjust the size of parallel splits to reduce\n    /// overhead, so this should not be needed.\n    ///\n    /// [`with_max_len`]: super::IndexedParallelIterator::with_max_len()\n    fn max_len(&self) -> usize {\n        usize::MAX\n    }\n\n    /// Split into two producers; one produces items `0..index`, the\n    /// other `index..N`. Index must be less than or equal to `N`.\n    fn split_at(self, index: usize) -> (Self, Self);\n\n    /// Iterate the producer, feeding each element to `folder`, and\n    /// stop when the folder is full (or all elements have been consumed).\n    ///\n    /// The provided implementation is sufficient for most iterables.\n    fn fold_with<F>(self, folder: F) -> F\n    where\n        F: Folder<Self::Item>,\n    {\n        folder.consume_iter(self.into_iter())\n    }\n}\n\n/// A consumer is effectively a [generalized \"fold\" operation][fold],\n/// and in fact each consumer will eventually be converted into a\n/// [`Folder`]. What makes a consumer special is that, like a\n/// [`Producer`], it can be **split** into multiple consumers using\n/// the `split_at` method. When a consumer is split, it produces two\n/// consumers, as well as a **reducer**. The two consumers can be fed\n/// items independently, and when they are done the reducer is used to\n/// combine their two results into one. See [the `plumbing`\n/// README][r] for further details.\n///\n/// [r]: https://github.com/rayon-rs/rayon/blob/main/src/iter/plumbing/README.md\n/// [fold]: Iterator::fold()\npub trait Consumer<Item>: Send + Sized {\n    /// The type of folder that this consumer can be converted into.\n    type Folder: Folder<Item, Result = Self::Result>;\n\n    /// The type of reducer that is produced if this consumer is split.\n    type Reducer: Reducer<Self::Result>;\n\n    /// The type of result that this consumer will ultimately produce.\n    type Result: Send;\n\n    /// Divide the consumer into two consumers, one processing items\n    /// `0..index` and one processing items from `index..`. Also\n    /// produces a reducer that can be used to reduce the results at\n    /// the end.\n    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer);\n\n    /// Convert the consumer into a folder that can consume items\n    /// sequentially, eventually producing a final result.\n    fn into_folder(self) -> Self::Folder;\n\n    /// Hint whether this `Consumer` would like to stop processing\n    /// further items, e.g. if a search has been completed.\n    fn full(&self) -> bool;\n}\n\n/// The `Folder` trait encapsulates [the standard fold\n/// operation][fold].  It can be fed many items using the `consume`\n/// method. At the end, once all items have been consumed, it can then\n/// be converted (using `complete`) into a final value.\n///\n/// [fold]: Iterator::fold()\npub trait Folder<Item>: Sized {\n    /// The type of result that will ultimately be produced by the folder.\n    type Result;\n\n    /// Consume next item and return new sequential state.\n    fn consume(self, item: Item) -> Self;\n\n    /// Consume items from the iterator until full, and return new sequential state.\n    ///\n    /// This method is **optional**. The default simply iterates over\n    /// `iter`, invoking `consume` and checking after each iteration\n    /// whether `full` returns false.\n    ///\n    /// The main reason to override it is if you can provide a more\n    /// specialized, efficient implementation.\n    fn consume_iter<I>(mut self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = Item>,\n    {\n        for item in iter {\n            self = self.consume(item);\n            if self.full() {\n                break;\n            }\n        }\n        self\n    }\n\n    /// Finish consuming items, produce final result.\n    fn complete(self) -> Self::Result;\n\n    /// Hint whether this `Folder` would like to stop processing\n    /// further items, e.g. if a search has been completed.\n    fn full(&self) -> bool;\n}\n\n/// The reducer is the final step of a `Consumer` -- after a consumer\n/// has been split into two parts, and each of those parts has been\n/// fully processed, we are left with two results. The reducer is then\n/// used to combine those two results into one. See [the `plumbing`\n/// README][r] for further details.\n///\n/// [r]: https://github.com/rayon-rs/rayon/blob/main/src/iter/plumbing/README.md\npub trait Reducer<Result> {\n    /// Reduce two final results into one; this is executed after a\n    /// split.\n    fn reduce(self, left: Result, right: Result) -> Result;\n}\n\n/// A stateless consumer can be freely copied. These consumers can be\n/// used like regular consumers, but they also support a\n/// `split_off_left` method that does not take an index to split, but\n/// simply splits at some arbitrary point (`for_each`, for example,\n/// produces an unindexed consumer).\npub trait UnindexedConsumer<I>: Consumer<I> {\n    /// Splits off a \"left\" consumer and returns it. The `self`\n    /// consumer should then be used to consume the \"right\" portion of\n    /// the data. (The ordering matters for methods like find_first --\n    /// values produced by the returned value are given precedence\n    /// over values produced by `self`.) Once the left and right\n    /// halves have been fully consumed, you should reduce the results\n    /// with the result of `to_reducer`.\n    fn split_off_left(&self) -> Self;\n\n    /// Creates a reducer that can be used to combine the results from\n    /// a split consumer.\n    fn to_reducer(&self) -> Self::Reducer;\n}\n\n/// A variant on `Producer` which does not know its exact length or\n/// cannot represent it in a `usize`. These producers act like\n/// ordinary producers except that they cannot be told to split at a\n/// particular point. Instead, you just ask them to split 'somewhere'.\n///\n/// (In principle, `Producer` could extend this trait; however, it\n/// does not because to do so would require producers to carry their\n/// own length with them.)\npub trait UnindexedProducer: Send + Sized {\n    /// The type of item returned by this producer.\n    type Item;\n\n    /// Split midway into a new producer if possible, otherwise return `None`.\n    fn split(self) -> (Self, Option<Self>);\n\n    /// Iterate the producer, feeding each element to `folder`, and\n    /// stop when the folder is full (or all elements have been consumed).\n    fn fold_with<F>(self, folder: F) -> F\n    where\n        F: Folder<Self::Item>;\n}\n\n/// A splitter controls the policy for splitting into smaller work items.\n///\n/// Thief-splitting is an adaptive policy that starts by splitting into\n/// enough jobs for every worker thread, and then resets itself whenever a\n/// job is actually stolen into a different thread.\n#[derive(Clone, Copy)]\nstruct Splitter {\n    /// The `splits` tell us approximately how many remaining times we'd\n    /// like to split this job.  We always just divide it by two though, so\n    /// the effective number of pieces will be `next_power_of_two()`.\n    splits: usize,\n}\n\nimpl Splitter {\n    #[inline]\n    fn new() -> Splitter {\n        Splitter {\n            splits: crate::current_num_threads(),\n        }\n    }\n\n    #[inline]\n    fn try_split(&mut self, stolen: bool) -> bool {\n        let Splitter { splits } = *self;\n\n        if stolen {\n            // This job was stolen!  Reset the number of desired splits to the\n            // thread count, if that's more than we had remaining anyway.\n            self.splits = Ord::max(crate::current_num_threads(), self.splits / 2);\n            true\n        } else if splits > 0 {\n            // We have splits remaining, make it so.\n            self.splits /= 2;\n            true\n        } else {\n            // Not stolen, and no more splits -- we're done!\n            false\n        }\n    }\n}\n\n/// The length splitter is built on thief-splitting, but additionally takes\n/// into account the remaining length of the iterator.\n#[derive(Clone, Copy)]\nstruct LengthSplitter {\n    inner: Splitter,\n\n    /// The smallest we're willing to divide into.  Usually this is just 1,\n    /// but you can choose a larger working size with `with_min_len()`.\n    min: usize,\n}\n\nimpl LengthSplitter {\n    /// Creates a new splitter based on lengths.\n    ///\n    /// The `min` is a hard lower bound.  We'll never split below that, but\n    /// of course an iterator might start out smaller already.\n    ///\n    /// The `max` is an upper bound on the working size, used to determine\n    /// the minimum number of times we need to split to get under that limit.\n    /// The adaptive algorithm may very well split even further, but never\n    /// smaller than the `min`.\n    #[inline]\n    fn new(min: usize, max: usize, len: usize) -> LengthSplitter {\n        let mut splitter = LengthSplitter {\n            inner: Splitter::new(),\n            min: Ord::max(min, 1),\n        };\n\n        // Divide the given length by the max working length to get the minimum\n        // number of splits we need to get under that max.  This rounds down,\n        // but the splitter actually gives `next_power_of_two()` pieces anyway.\n        // e.g. len 12345 / max 100 = 123 min_splits -> 128 pieces.\n        let min_splits = len / Ord::max(max, 1);\n\n        // Only update the value if it's not splitting enough already.\n        if min_splits > splitter.inner.splits {\n            splitter.inner.splits = min_splits;\n        }\n\n        splitter\n    }\n\n    #[inline]\n    fn try_split(&mut self, len: usize, stolen: bool) -> bool {\n        // If splitting wouldn't make us too small, try the inner splitter.\n        len / 2 >= self.min && self.inner.try_split(stolen)\n    }\n}\n\n/// This helper function is used to \"connect\" a parallel iterator to a\n/// consumer. It will convert the `par_iter` into a producer P and\n/// then pull items from P and feed them to `consumer`, splitting and\n/// creating parallel threads as needed.\n///\n/// This is useful when you are implementing your own parallel\n/// iterators: it is often used as the definition of the\n/// [`drive_unindexed`] or [`drive`] methods.\n///\n/// [`drive_unindexed`]: super::ParallelIterator::drive_unindexed()\n/// [`drive`]: super::IndexedParallelIterator::drive()\npub fn bridge<I, C>(par_iter: I, consumer: C) -> C::Result\nwhere\n    I: IndexedParallelIterator,\n    C: Consumer<I::Item>,\n{\n    let len = par_iter.len();\n    return par_iter.with_producer(Callback { len, consumer });\n\n    struct Callback<C> {\n        len: usize,\n        consumer: C,\n    }\n\n    impl<C, I> ProducerCallback<I> for Callback<C>\n    where\n        C: Consumer<I>,\n    {\n        type Output = C::Result;\n        fn callback<P>(self, producer: P) -> C::Result\n        where\n            P: Producer<Item = I>,\n        {\n            bridge_producer_consumer(self.len, producer, self.consumer)\n        }\n    }\n}\n\n/// This helper function is used to \"connect\" a producer and a\n/// consumer. You may prefer to call [`bridge()`], which wraps this\n/// function. This function will draw items from `producer` and feed\n/// them to `consumer`, splitting and creating parallel tasks when\n/// needed.\n///\n/// This is useful when you are implementing your own parallel\n/// iterators: it is often used as the definition of the\n/// [`drive_unindexed`] or [`drive`] methods.\n///\n/// [`drive_unindexed`]: super::ParallelIterator::drive_unindexed()\n/// [`drive`]: super::IndexedParallelIterator::drive()\npub fn bridge_producer_consumer<P, C>(len: usize, producer: P, consumer: C) -> C::Result\nwhere\n    P: Producer,\n    C: Consumer<P::Item>,\n{\n    let splitter = LengthSplitter::new(producer.min_len(), producer.max_len(), len);\n    return helper(len, false, splitter, producer, consumer);\n\n    fn helper<P, C>(\n        len: usize,\n        migrated: bool,\n        mut splitter: LengthSplitter,\n        producer: P,\n        consumer: C,\n    ) -> C::Result\n    where\n        P: Producer,\n        C: Consumer<P::Item>,\n    {\n        if consumer.full() {\n            consumer.into_folder().complete()\n        } else if splitter.try_split(len, migrated) {\n            let mid = len / 2;\n            let (left_producer, right_producer) = producer.split_at(mid);\n            let (left_consumer, right_consumer, reducer) = consumer.split_at(mid);\n            let (left_result, right_result) = join_context(\n                |context| {\n                    helper(\n                        mid,\n                        context.migrated(),\n                        splitter,\n                        left_producer,\n                        left_consumer,\n                    )\n                },\n                |context| {\n                    helper(\n                        len - mid,\n                        context.migrated(),\n                        splitter,\n                        right_producer,\n                        right_consumer,\n                    )\n                },\n            );\n            reducer.reduce(left_result, right_result)\n        } else {\n            producer.fold_with(consumer.into_folder()).complete()\n        }\n    }\n}\n\n/// A variant of [`bridge_producer_consumer()`] where the producer is an unindexed producer.\npub fn bridge_unindexed<P, C>(producer: P, consumer: C) -> C::Result\nwhere\n    P: UnindexedProducer,\n    C: UnindexedConsumer<P::Item>,\n{\n    let splitter = Splitter::new();\n    bridge_unindexed_producer_consumer(false, splitter, producer, consumer)\n}\n\nfn bridge_unindexed_producer_consumer<P, C>(\n    migrated: bool,\n    mut splitter: Splitter,\n    producer: P,\n    consumer: C,\n) -> C::Result\nwhere\n    P: UnindexedProducer,\n    C: UnindexedConsumer<P::Item>,\n{\n    if consumer.full() {\n        consumer.into_folder().complete()\n    } else if splitter.try_split(migrated) {\n        match producer.split() {\n            (left_producer, Some(right_producer)) => {\n                let (reducer, left_consumer, right_consumer) =\n                    (consumer.to_reducer(), consumer.split_off_left(), consumer);\n                let bridge = bridge_unindexed_producer_consumer;\n                let (left_result, right_result) = join_context(\n                    |context| bridge(context.migrated(), splitter, left_producer, left_consumer),\n                    |context| bridge(context.migrated(), splitter, right_producer, right_consumer),\n                );\n                reducer.reduce(left_result, right_result)\n            }\n            (producer, None) => producer.fold_with(consumer.into_folder()).complete(),\n        }\n    } else {\n        producer.fold_with(consumer.into_folder()).complete()\n    }\n}\n"
  },
  {
    "path": "src/iter/positions.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\n\n/// `Positions` takes a predicate `predicate` and filters out elements that match,\n/// yielding their indices.\n///\n/// This struct is created by the [`positions()`] method on [`IndexedParallelIterator`]\n///\n/// [`positions()`]: IndexedParallelIterator::positions()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Clone)]\npub struct Positions<I, P> {\n    base: I,\n    predicate: P,\n}\n\nimpl<I: Debug, P> Debug for Positions<I, P> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"Positions\")\n            .field(\"base\", &self.base)\n            .finish()\n    }\n}\n\nimpl<I, P> Positions<I, P> {\n    /// Create a new `Positions` iterator.\n    pub(super) fn new(base: I, predicate: P) -> Self {\n        Positions { base, predicate }\n    }\n}\n\nimpl<I, P> ParallelIterator for Positions<I, P>\nwhere\n    I: IndexedParallelIterator,\n    P: Fn(I::Item) -> bool + Sync + Send,\n{\n    type Item = usize;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer1 = PositionsConsumer::new(consumer, &self.predicate, 0);\n        self.base.drive(consumer1)\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Consumer implementation\n\nstruct PositionsConsumer<'p, C, P> {\n    base: C,\n    predicate: &'p P,\n    offset: usize,\n}\n\nimpl<'p, C, P> PositionsConsumer<'p, C, P> {\n    fn new(base: C, predicate: &'p P, offset: usize) -> Self {\n        PositionsConsumer {\n            base,\n            predicate,\n            offset,\n        }\n    }\n}\n\nimpl<'p, T, C, P> Consumer<T> for PositionsConsumer<'p, C, P>\nwhere\n    C: Consumer<usize>,\n    P: Fn(T) -> bool + Sync,\n{\n    type Folder = PositionsFolder<'p, C::Folder, P>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, C::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            PositionsConsumer::new(left, self.predicate, self.offset),\n            PositionsConsumer::new(right, self.predicate, self.offset + index),\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        PositionsFolder {\n            base: self.base.into_folder(),\n            predicate: self.predicate,\n            offset: self.offset,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\nstruct PositionsFolder<'p, F, P> {\n    base: F,\n    predicate: &'p P,\n    offset: usize,\n}\n\nimpl<F, P, T> Folder<T> for PositionsFolder<'_, F, P>\nwhere\n    F: Folder<usize>,\n    P: Fn(T) -> bool,\n{\n    type Result = F::Result;\n\n    fn consume(mut self, item: T) -> Self {\n        let index = self.offset;\n        self.offset += 1;\n        if (self.predicate)(item) {\n            self.base = self.base.consume(index);\n        }\n        self\n    }\n\n    // This cannot easily specialize `consume_iter` to be better than\n    // the default, because that requires checking `self.base.full()`\n    // during a call to `self.base.consume_iter()`. (#632)\n\n    fn complete(self) -> Self::Result {\n        self.base.complete()\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n"
  },
  {
    "path": "src/iter/product.rs",
    "content": "use super::plumbing::*;\nuse super::ParallelIterator;\n\nuse std::iter::{self, Product};\nuse std::marker::PhantomData;\n\npub(super) fn product<PI, P>(pi: PI) -> P\nwhere\n    PI: ParallelIterator,\n    P: Send + Product<PI::Item> + Product,\n{\n    pi.drive_unindexed(ProductConsumer::new())\n}\n\nfn mul<T: Product>(left: T, right: T) -> T {\n    [left, right].into_iter().product()\n}\n\nstruct ProductConsumer<P: Send> {\n    _marker: PhantomData<*const P>,\n}\n\nunsafe impl<P: Send> Send for ProductConsumer<P> {}\n\nimpl<P: Send> ProductConsumer<P> {\n    fn new() -> ProductConsumer<P> {\n        ProductConsumer {\n            _marker: PhantomData,\n        }\n    }\n}\n\nimpl<P, T> Consumer<T> for ProductConsumer<P>\nwhere\n    P: Send + Product<T> + Product,\n{\n    type Folder = ProductFolder<P>;\n    type Reducer = Self;\n    type Result = P;\n\n    fn split_at(self, _index: usize) -> (Self, Self, Self) {\n        (\n            ProductConsumer::new(),\n            ProductConsumer::new(),\n            ProductConsumer::new(),\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        ProductFolder {\n            product: iter::empty::<T>().product(),\n        }\n    }\n\n    fn full(&self) -> bool {\n        false\n    }\n}\n\nimpl<P, T> UnindexedConsumer<T> for ProductConsumer<P>\nwhere\n    P: Send + Product<T> + Product,\n{\n    fn split_off_left(&self) -> Self {\n        ProductConsumer::new()\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        ProductConsumer::new()\n    }\n}\n\nimpl<P> Reducer<P> for ProductConsumer<P>\nwhere\n    P: Send + Product,\n{\n    fn reduce(self, left: P, right: P) -> P {\n        mul(left, right)\n    }\n}\n\nstruct ProductFolder<P> {\n    product: P,\n}\n\nimpl<P, T> Folder<T> for ProductFolder<P>\nwhere\n    P: Product<T> + Product,\n{\n    type Result = P;\n\n    fn consume(self, item: T) -> Self {\n        ProductFolder {\n            product: mul(self.product, iter::once(item).product()),\n        }\n    }\n\n    fn consume_iter<I>(self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = T>,\n    {\n        ProductFolder {\n            product: mul(self.product, iter.into_iter().product()),\n        }\n    }\n\n    fn complete(self) -> P {\n        self.product\n    }\n\n    fn full(&self) -> bool {\n        false\n    }\n}\n"
  },
  {
    "path": "src/iter/reduce.rs",
    "content": "use super::plumbing::*;\nuse super::ParallelIterator;\n\npub(super) fn reduce<PI, R, ID, T>(pi: PI, identity: ID, reduce_op: R) -> T\nwhere\n    PI: ParallelIterator<Item = T>,\n    R: Fn(T, T) -> T + Sync,\n    ID: Fn() -> T + Sync,\n    T: Send,\n{\n    let consumer = ReduceConsumer {\n        identity: &identity,\n        reduce_op: &reduce_op,\n    };\n    pi.drive_unindexed(consumer)\n}\n\nstruct ReduceConsumer<'r, R, ID> {\n    identity: &'r ID,\n    reduce_op: &'r R,\n}\n\nimpl<'r, R, ID> Copy for ReduceConsumer<'r, R, ID> {}\n\nimpl<'r, R, ID> Clone for ReduceConsumer<'r, R, ID> {\n    fn clone(&self) -> Self {\n        *self\n    }\n}\n\nimpl<'r, R, ID, T> Consumer<T> for ReduceConsumer<'r, R, ID>\nwhere\n    R: Fn(T, T) -> T + Sync,\n    ID: Fn() -> T + Sync,\n    T: Send,\n{\n    type Folder = ReduceFolder<'r, R, T>;\n    type Reducer = Self;\n    type Result = T;\n\n    fn split_at(self, _index: usize) -> (Self, Self, Self) {\n        (self, self, self)\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        ReduceFolder {\n            reduce_op: self.reduce_op,\n            item: (self.identity)(),\n        }\n    }\n\n    fn full(&self) -> bool {\n        false\n    }\n}\n\nimpl<'r, R, ID, T> UnindexedConsumer<T> for ReduceConsumer<'r, R, ID>\nwhere\n    R: Fn(T, T) -> T + Sync,\n    ID: Fn() -> T + Sync,\n    T: Send,\n{\n    fn split_off_left(&self) -> Self {\n        *self\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        *self\n    }\n}\n\nimpl<'r, R, ID, T> Reducer<T> for ReduceConsumer<'r, R, ID>\nwhere\n    R: Fn(T, T) -> T + Sync,\n{\n    fn reduce(self, left: T, right: T) -> T {\n        (self.reduce_op)(left, right)\n    }\n}\n\nstruct ReduceFolder<'r, R, T> {\n    reduce_op: &'r R,\n    item: T,\n}\n\nimpl<'r, R, T> Folder<T> for ReduceFolder<'r, R, T>\nwhere\n    R: Fn(T, T) -> T,\n{\n    type Result = T;\n\n    fn consume(self, item: T) -> Self {\n        ReduceFolder {\n            reduce_op: self.reduce_op,\n            item: (self.reduce_op)(self.item, item),\n        }\n    }\n\n    fn consume_iter<I>(self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = T>,\n    {\n        ReduceFolder {\n            reduce_op: self.reduce_op,\n            item: iter.into_iter().fold(self.item, self.reduce_op),\n        }\n    }\n\n    fn complete(self) -> T {\n        self.item\n    }\n\n    fn full(&self) -> bool {\n        false\n    }\n}\n"
  },
  {
    "path": "src/iter/repeat.rs",
    "content": "use super::plumbing::*;\nuse super::*;\nuse std::num::NonZeroUsize;\nuse std::{fmt, iter, mem};\n\n/// Iterator adaptor for [the `repeat()` function].\n///\n/// [the `repeat()` function]: repeat()\n#[derive(Debug, Clone)]\npub struct Repeat<T> {\n    element: T,\n}\n\n/// Creates a parallel iterator that endlessly repeats `element` (by\n/// cloning it). Note that this iterator has \"infinite\" length, so\n/// typically you would want to use `zip` or `take` or some other\n/// means to shorten it, or consider using\n/// [the `repeat_n()` function] instead.\n///\n/// [the `repeat_n()` function]: repeat_n()\n///\n/// # Examples\n///\n/// ```\n/// use rayon::prelude::*;\n/// use rayon::iter::repeat;\n/// let x: Vec<(i32, i32)> = repeat(22).zip(0..3).collect();\n/// assert_eq!(x, vec![(22, 0), (22, 1), (22, 2)]);\n/// ```\npub fn repeat<T: Clone + Send>(element: T) -> Repeat<T> {\n    Repeat { element }\n}\n\nimpl<T> Repeat<T>\nwhere\n    T: Clone + Send,\n{\n    /// Takes only `n` repeats of the element, similar to the general\n    /// [`take()`].\n    ///\n    /// The resulting `RepeatN` is an `IndexedParallelIterator`, allowing\n    /// more functionality than `Repeat` alone.\n    ///\n    /// [`take()`]: IndexedParallelIterator::take()\n    pub fn take(self, n: usize) -> RepeatN<T> {\n        repeat_n(self.element, n)\n    }\n\n    /// Iterates tuples, repeating the element with items from another\n    /// iterator, similar to the general [`zip()`].\n    ///\n    /// [`zip()`]: IndexedParallelIterator::zip()\n    pub fn zip<Z>(self, zip_op: Z) -> Zip<RepeatN<T>, Z::Iter>\n    where\n        Z: IntoParallelIterator<Iter: IndexedParallelIterator>,\n    {\n        let z = zip_op.into_par_iter();\n        let n = z.len();\n        self.take(n).zip(z)\n    }\n}\n\nimpl<T> ParallelIterator for Repeat<T>\nwhere\n    T: Clone + Send,\n{\n    type Item = T;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let producer = RepeatProducer {\n            element: self.element,\n        };\n        bridge_unindexed(producer, consumer)\n    }\n}\n\n/// Unindexed producer for `Repeat`.\nstruct RepeatProducer<T: Clone + Send> {\n    element: T,\n}\n\nimpl<T: Clone + Send> UnindexedProducer for RepeatProducer<T> {\n    type Item = T;\n\n    fn split(self) -> (Self, Option<Self>) {\n        (\n            RepeatProducer {\n                element: self.element.clone(),\n            },\n            Some(RepeatProducer {\n                element: self.element,\n            }),\n        )\n    }\n\n    fn fold_with<F>(self, folder: F) -> F\n    where\n        F: Folder<T>,\n    {\n        folder.consume_iter(iter::repeat(self.element))\n    }\n}\n\n/// Iterator adaptor for [the `repeat_n()` function].\n///\n/// [the `repeat_n()` function]: repeat_n()\n#[derive(Clone)]\npub struct RepeatN<T> {\n    inner: RepeatNProducer<T>,\n}\n\n/// Creates a parallel iterator that produces `n` repeats of `element`\n/// (by cloning it).\n///\n/// # Examples\n///\n/// ```\n/// use rayon::prelude::*;\n/// use rayon::iter::repeat_n;\n/// let x: Vec<(i32, i32)> = repeat_n(22, 3).zip(0..3).collect();\n/// assert_eq!(x, vec![(22, 0), (22, 1), (22, 2)]);\n/// ```\npub fn repeat_n<T: Clone + Send>(element: T, n: usize) -> RepeatN<T> {\n    let inner = match NonZeroUsize::new(n) {\n        Some(count) => RepeatNProducer::Repeats(element, count),\n        None => RepeatNProducer::Empty,\n    };\n    RepeatN { inner }\n}\n\n/// Creates a parallel iterator that produces `n` repeats of `element`\n/// (by cloning it).\n///\n/// Deprecated in favor of [`repeat_n`] for consistency with the standard library.\n#[deprecated(note = \"use `repeat_n`\")]\npub fn repeatn<T: Clone + Send>(element: T, n: usize) -> RepeatN<T> {\n    repeat_n(element, n)\n}\n\nimpl<T: fmt::Debug> fmt::Debug for RepeatN<T> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        let mut dbg = f.debug_struct(\"RepeatN\");\n        if let RepeatNProducer::Repeats(element, count) = &self.inner {\n            dbg.field(\"count\", &count.get())\n                .field(\"element\", element)\n                .finish()\n        } else {\n            dbg.field(\"count\", &0usize).finish_non_exhaustive()\n        }\n    }\n}\n\nimpl<T> ParallelIterator for RepeatN<T>\nwhere\n    T: Clone + Send,\n{\n    type Item = T;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.inner.len())\n    }\n}\n\nimpl<T> IndexedParallelIterator for RepeatN<T>\nwhere\n    T: Clone + Send,\n{\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        callback.callback(self.inner)\n    }\n\n    fn len(&self) -> usize {\n        self.inner.len()\n    }\n}\n\n/// Producer for `RepeatN`.\n#[derive(Clone)]\nenum RepeatNProducer<T> {\n    Repeats(T, NonZeroUsize),\n    Empty,\n}\n\nimpl<T: Clone + Send> Producer for RepeatNProducer<T> {\n    type Item = T;\n    type IntoIter = Self;\n\n    fn into_iter(self) -> Self::IntoIter {\n        // We could potentially use `std::iter::RepeatN` with MSRV 1.82, but we have no way to\n        // create an empty instance without a value in hand, like `repeat_n(value, 0)`.\n        self\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        if let Self::Repeats(element, count) = self {\n            assert!(index <= count.get());\n            match (\n                NonZeroUsize::new(index),\n                NonZeroUsize::new(count.get() - index),\n            ) {\n                (Some(left), Some(right)) => (\n                    Self::Repeats(element.clone(), left),\n                    Self::Repeats(element, right),\n                ),\n                (Some(left), None) => (Self::Repeats(element, left), Self::Empty),\n                (None, Some(right)) => (Self::Empty, Self::Repeats(element, right)),\n                (None, None) => unreachable!(),\n            }\n        } else {\n            assert!(index == 0);\n            (Self::Empty, Self::Empty)\n        }\n    }\n}\n\nimpl<T: Clone> Iterator for RepeatNProducer<T> {\n    type Item = T;\n\n    #[inline]\n    fn next(&mut self) -> Option<T> {\n        if let Self::Repeats(element, count) = self {\n            if let Some(rem) = NonZeroUsize::new(count.get() - 1) {\n                *count = rem;\n                Some(element.clone())\n            } else {\n                match mem::replace(self, Self::Empty) {\n                    Self::Repeats(element, _) => Some(element),\n                    Self::Empty => unreachable!(),\n                }\n            }\n        } else {\n            None\n        }\n    }\n\n    #[inline]\n    fn nth(&mut self, n: usize) -> Option<T> {\n        if let Self::Repeats(_, count) = self {\n            if let Some(rem) = NonZeroUsize::new(count.get().saturating_sub(n)) {\n                *count = rem;\n                return self.next();\n            }\n            *self = Self::Empty;\n        }\n        None\n    }\n\n    #[inline]\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        let len = self.len();\n        (len, Some(len))\n    }\n}\n\nimpl<T: Clone> DoubleEndedIterator for RepeatNProducer<T> {\n    #[inline]\n    fn next_back(&mut self) -> Option<T> {\n        self.next()\n    }\n\n    #[inline]\n    fn nth_back(&mut self, n: usize) -> Option<T> {\n        self.nth(n)\n    }\n}\n\nimpl<T: Clone> ExactSizeIterator for RepeatNProducer<T> {\n    #[inline]\n    fn len(&self) -> usize {\n        match self {\n            Self::Repeats(_, count) => count.get(),\n            Self::Empty => 0,\n        }\n    }\n}\n"
  },
  {
    "path": "src/iter/rev.rs",
    "content": "use super::plumbing::*;\nuse super::*;\nuse std::iter;\n\n/// `Rev` is an iterator that produces elements in reverse order. This struct\n/// is created by the [`rev()`] method on [`IndexedParallelIterator`]\n///\n/// [`rev()`]: IndexedParallelIterator::rev()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\npub struct Rev<I> {\n    base: I,\n}\n\nimpl<I> Rev<I> {\n    /// Creates a new `Rev` iterator.\n    pub(super) fn new(base: I) -> Self {\n        Rev { base }\n    }\n}\n\nimpl<I> ParallelIterator for Rev<I>\nwhere\n    I: IndexedParallelIterator,\n{\n    type Item = I::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<I> IndexedParallelIterator for Rev<I>\nwhere\n    I: IndexedParallelIterator,\n{\n    fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.base.len()\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        let len = self.base.len();\n        return self.base.with_producer(Callback { callback, len });\n\n        struct Callback<CB> {\n            callback: CB,\n            len: usize,\n        }\n\n        impl<T, CB> ProducerCallback<T> for Callback<CB>\n        where\n            CB: ProducerCallback<T>,\n        {\n            type Output = CB::Output;\n            fn callback<P>(self, base: P) -> CB::Output\n            where\n                P: Producer<Item = T>,\n            {\n                let producer = RevProducer {\n                    base,\n                    len: self.len,\n                };\n                self.callback.callback(producer)\n            }\n        }\n    }\n}\n\nstruct RevProducer<P> {\n    base: P,\n    len: usize,\n}\n\nimpl<P> Producer for RevProducer<P>\nwhere\n    P: Producer,\n{\n    type Item = P::Item;\n    type IntoIter = iter::Rev<P::IntoIter>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.base.into_iter().rev()\n    }\n\n    fn min_len(&self) -> usize {\n        self.base.min_len()\n    }\n    fn max_len(&self) -> usize {\n        self.base.max_len()\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let (left, right) = self.base.split_at(self.len - index);\n        (\n            RevProducer {\n                base: right,\n                len: index,\n            },\n            RevProducer {\n                base: left,\n                len: self.len - index,\n            },\n        )\n    }\n}\n"
  },
  {
    "path": "src/iter/skip.rs",
    "content": "use super::noop::NoopConsumer;\nuse super::plumbing::*;\nuse super::*;\n\n/// `Skip` is an iterator that skips over the first `n` elements.\n/// This struct is created by the [`skip()`] method on [`IndexedParallelIterator`]\n///\n/// [`skip()`]: IndexedParallelIterator::skip()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\npub struct Skip<I> {\n    base: I,\n    n: usize,\n}\n\nimpl<I> Skip<I>\nwhere\n    I: IndexedParallelIterator,\n{\n    /// Creates a new `Skip` iterator.\n    pub(super) fn new(base: I, n: usize) -> Self {\n        let n = Ord::min(base.len(), n);\n        Skip { base, n }\n    }\n}\n\nimpl<I> ParallelIterator for Skip<I>\nwhere\n    I: IndexedParallelIterator,\n{\n    type Item = I::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<I> IndexedParallelIterator for Skip<I>\nwhere\n    I: IndexedParallelIterator,\n{\n    fn len(&self) -> usize {\n        self.base.len() - self.n\n    }\n\n    fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result {\n        bridge(self, consumer)\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        return self.base.with_producer(Callback {\n            callback,\n            n: self.n,\n        });\n\n        struct Callback<CB> {\n            callback: CB,\n            n: usize,\n        }\n\n        impl<T, CB> ProducerCallback<T> for Callback<CB>\n        where\n            CB: ProducerCallback<T>,\n        {\n            type Output = CB::Output;\n            fn callback<P>(self, base: P) -> CB::Output\n            where\n                P: Producer<Item = T>,\n            {\n                crate::in_place_scope(|scope| {\n                    let Self { callback, n } = self;\n                    let (before_skip, after_skip) = base.split_at(n);\n\n                    // Run the skipped part separately for side effects.\n                    // We'll still get any panics propagated back by the scope.\n                    scope.spawn(move |_| bridge_producer_consumer(n, before_skip, NoopConsumer));\n\n                    callback.callback(after_skip)\n                })\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/iter/skip_any.rs",
    "content": "use super::plumbing::*;\nuse super::*;\nuse std::sync::atomic::{AtomicUsize, Ordering};\n\n/// `SkipAny` is an iterator that skips over `n` elements from anywhere in `I`.\n/// This struct is created by the [`skip_any()`] method on [`ParallelIterator`]\n///\n/// [`skip_any()`]: ParallelIterator::skip_any()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Clone, Debug)]\npub struct SkipAny<I> {\n    base: I,\n    count: usize,\n}\n\nimpl<I> SkipAny<I> {\n    /// Creates a new `SkipAny` iterator.\n    pub(super) fn new(base: I, count: usize) -> Self {\n        SkipAny { base, count }\n    }\n}\n\nimpl<I> ParallelIterator for SkipAny<I>\nwhere\n    I: ParallelIterator,\n{\n    type Item = I::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer1 = SkipAnyConsumer {\n            base: consumer,\n            count: &AtomicUsize::new(self.count),\n        };\n        self.base.drive_unindexed(consumer1)\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Consumer implementation\n\nstruct SkipAnyConsumer<'f, C> {\n    base: C,\n    count: &'f AtomicUsize,\n}\n\nimpl<'f, T, C> Consumer<T> for SkipAnyConsumer<'f, C>\nwhere\n    C: Consumer<T>,\n    T: Send,\n{\n    type Folder = SkipAnyFolder<'f, C::Folder>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            SkipAnyConsumer { base: left, ..self },\n            SkipAnyConsumer {\n                base: right,\n                ..self\n            },\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        SkipAnyFolder {\n            base: self.base.into_folder(),\n            count: self.count,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\nimpl<'f, T, C> UnindexedConsumer<T> for SkipAnyConsumer<'f, C>\nwhere\n    C: UnindexedConsumer<T>,\n    T: Send,\n{\n    fn split_off_left(&self) -> Self {\n        SkipAnyConsumer {\n            base: self.base.split_off_left(),\n            ..*self\n        }\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n\nstruct SkipAnyFolder<'f, C> {\n    base: C,\n    count: &'f AtomicUsize,\n}\n\nfn checked_decrement(u: &AtomicUsize) -> bool {\n    u.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |u| u.checked_sub(1))\n        .is_ok()\n}\n\nimpl<'f, T, C> Folder<T> for SkipAnyFolder<'f, C>\nwhere\n    C: Folder<T>,\n{\n    type Result = C::Result;\n\n    fn consume(mut self, item: T) -> Self {\n        if !checked_decrement(self.count) {\n            self.base = self.base.consume(item);\n        }\n        self\n    }\n\n    fn consume_iter<I>(mut self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = T>,\n    {\n        self.base = self.base.consume_iter(\n            iter.into_iter()\n                .skip_while(move |_| checked_decrement(self.count)),\n        );\n        self\n    }\n\n    fn complete(self) -> C::Result {\n        self.base.complete()\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n"
  },
  {
    "path": "src/iter/skip_any_while.rs",
    "content": "use super::plumbing::*;\nuse super::*;\nuse std::fmt;\nuse std::sync::atomic::{AtomicBool, Ordering};\n\n/// `SkipAnyWhile` is an iterator that skips over elements from anywhere in `I`\n/// until the callback returns `false`.\n/// This struct is created by the [`skip_any_while()`] method on [`ParallelIterator`]\n///\n/// [`skip_any_while()`]: ParallelIterator::skip_any_while()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Clone)]\npub struct SkipAnyWhile<I, P> {\n    base: I,\n    predicate: P,\n}\n\nimpl<I: fmt::Debug, P> fmt::Debug for SkipAnyWhile<I, P> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"SkipAnyWhile\")\n            .field(\"base\", &self.base)\n            .finish()\n    }\n}\n\nimpl<I, P> SkipAnyWhile<I, P> {\n    /// Creates a new `SkipAnyWhile` iterator.\n    pub(super) fn new(base: I, predicate: P) -> Self {\n        SkipAnyWhile { base, predicate }\n    }\n}\n\nimpl<I, P> ParallelIterator for SkipAnyWhile<I, P>\nwhere\n    I: ParallelIterator,\n    P: Fn(&I::Item) -> bool + Sync + Send,\n{\n    type Item = I::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer1 = SkipAnyWhileConsumer {\n            base: consumer,\n            predicate: &self.predicate,\n            skipping: &AtomicBool::new(true),\n        };\n        self.base.drive_unindexed(consumer1)\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Consumer implementation\n\nstruct SkipAnyWhileConsumer<'p, C, P> {\n    base: C,\n    predicate: &'p P,\n    skipping: &'p AtomicBool,\n}\n\nimpl<'p, T, C, P> Consumer<T> for SkipAnyWhileConsumer<'p, C, P>\nwhere\n    C: Consumer<T>,\n    P: Fn(&T) -> bool + Sync,\n{\n    type Folder = SkipAnyWhileFolder<'p, C::Folder, P>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            SkipAnyWhileConsumer { base: left, ..self },\n            SkipAnyWhileConsumer {\n                base: right,\n                ..self\n            },\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        SkipAnyWhileFolder {\n            base: self.base.into_folder(),\n            predicate: self.predicate,\n            skipping: self.skipping,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\nimpl<'p, T, C, P> UnindexedConsumer<T> for SkipAnyWhileConsumer<'p, C, P>\nwhere\n    C: UnindexedConsumer<T>,\n    P: Fn(&T) -> bool + Sync,\n{\n    fn split_off_left(&self) -> Self {\n        SkipAnyWhileConsumer {\n            base: self.base.split_off_left(),\n            ..*self\n        }\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n\nstruct SkipAnyWhileFolder<'p, C, P> {\n    base: C,\n    predicate: &'p P,\n    skipping: &'p AtomicBool,\n}\n\nfn skip<T>(item: &T, skipping: &AtomicBool, predicate: &impl Fn(&T) -> bool) -> bool {\n    if !skipping.load(Ordering::Relaxed) {\n        return false;\n    }\n    if predicate(item) {\n        return true;\n    }\n    skipping.store(false, Ordering::Relaxed);\n    false\n}\n\nimpl<'p, T, C, P> Folder<T> for SkipAnyWhileFolder<'p, C, P>\nwhere\n    C: Folder<T>,\n    P: Fn(&T) -> bool + 'p,\n{\n    type Result = C::Result;\n\n    fn consume(mut self, item: T) -> Self {\n        if !skip(&item, self.skipping, self.predicate) {\n            self.base = self.base.consume(item);\n        }\n        self\n    }\n\n    fn consume_iter<I>(mut self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = T>,\n    {\n        self.base = self.base.consume_iter(\n            iter.into_iter()\n                .skip_while(move |x| skip(x, self.skipping, self.predicate)),\n        );\n        self\n    }\n\n    fn complete(self) -> C::Result {\n        self.base.complete()\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n"
  },
  {
    "path": "src/iter/splitter.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\n\n/// The `split` function takes arbitrary data and a closure that knows how to\n/// split it, and turns this into a `ParallelIterator`.\n///\n/// # Examples\n///\n/// As a simple example, Rayon can recursively split ranges of indices\n///\n/// ```\n/// use rayon::iter;\n/// use rayon::prelude::*;\n/// use std::ops::Range;\n///\n///\n/// // We define a range of indices as follows\n/// type Range1D = Range<usize>;\n///\n/// // Splitting it in two can be done like this\n/// fn split_range1(r: Range1D) -> (Range1D, Option<Range1D>) {\n///     // We are mathematically unable to split the range if there is only\n///     // one point inside of it, but we could stop splitting before that.\n///     if r.end - r.start <= 1 { return (r, None); }\n///\n///     // Here, our range is considered large enough to be splittable\n///     let midpoint = r.start + (r.end - r.start) / 2;\n///     (r.start..midpoint, Some(midpoint..r.end))\n/// }\n///\n/// // By using iter::split, Rayon will split the range until it has enough work\n/// // to feed the CPU cores, then give us the resulting sub-ranges\n/// iter::split(0..4096, split_range1).for_each(|sub_range| {\n///     // As our initial range had a power-of-two size, the final sub-ranges\n///     // should have power-of-two sizes too\n///     assert!((sub_range.end - sub_range.start).is_power_of_two());\n/// });\n/// ```\n///\n/// This recursive splitting can be extended to two or three dimensions,\n/// to reproduce a classic \"block-wise\" parallelization scheme of graphics and\n/// numerical simulations:\n///\n/// ```\n/// # use rayon::iter;\n/// # use rayon::prelude::*;\n/// # use std::ops::Range;\n/// # type Range1D = Range<usize>;\n/// # fn split_range1(r: Range1D) -> (Range1D, Option<Range1D>) {\n/// #     if r.end - r.start <= 1 { return (r, None); }\n/// #     let midpoint = r.start + (r.end - r.start) / 2;\n/// #     (r.start..midpoint, Some(midpoint..r.end))\n/// # }\n/// #\n/// // A two-dimensional range of indices can be built out of two 1D ones\n/// struct Range2D {\n///     // Range of horizontal indices\n///     pub rx: Range1D,\n///\n///     // Range of vertical indices\n///     pub ry: Range1D,\n/// }\n///\n/// // We want to recursively split them by the largest dimension until we have\n/// // enough sub-ranges to feed our mighty multi-core CPU. This function\n/// // carries out one such split.\n/// fn split_range2(r2: Range2D) -> (Range2D, Option<Range2D>) {\n///     // Decide on which axis (horizontal/vertical) the range should be split\n///     let width = r2.rx.end - r2.rx.start;\n///     let height = r2.ry.end - r2.ry.start;\n///     if width >= height {\n///         // This is a wide range, split it on the horizontal axis\n///         let (split_rx, ry) = (split_range1(r2.rx), r2.ry);\n///         let out1 = Range2D {\n///             rx: split_rx.0,\n///             ry: ry.clone(),\n///         };\n///         let out2 = split_rx.1.map(|rx| Range2D { rx, ry });\n///         (out1, out2)\n///     } else {\n///         // This is a tall range, split it on the vertical axis\n///         let (rx, split_ry) = (r2.rx, split_range1(r2.ry));\n///         let out1 = Range2D {\n///             rx: rx.clone(),\n///             ry: split_ry.0,\n///         };\n///         let out2 = split_ry.1.map(|ry| Range2D { rx, ry, });\n///         (out1, out2)\n///     }\n/// }\n///\n/// // Again, rayon can handle the recursive splitting for us\n/// let range = Range2D { rx: 0..800, ry: 0..600 };\n/// iter::split(range, split_range2).for_each(|sub_range| {\n///     // If the sub-ranges were indeed split by the largest dimension, then\n///     // if no dimension was twice larger than the other initially, this\n///     // property will remain true in the final sub-ranges.\n///     let width = sub_range.rx.end - sub_range.rx.start;\n///     let height = sub_range.ry.end - sub_range.ry.start;\n///     assert!((width / 2 <= height) && (height / 2 <= width));\n/// });\n/// ```\n///\npub fn split<D, S>(data: D, splitter: S) -> Split<D, S>\nwhere\n    D: Send,\n    S: Fn(D) -> (D, Option<D>) + Sync,\n{\n    Split { data, splitter }\n}\n\n/// `Split` is a parallel iterator using arbitrary data and a splitting function.\n/// This struct is created by the [`split()`] function.\n#[derive(Clone)]\npub struct Split<D, S> {\n    data: D,\n    splitter: S,\n}\n\nimpl<D: Debug, S> Debug for Split<D, S> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"Split\").field(\"data\", &self.data).finish()\n    }\n}\n\nimpl<D, S> ParallelIterator for Split<D, S>\nwhere\n    D: Send,\n    S: Fn(D) -> (D, Option<D>) + Sync + Send,\n{\n    type Item = D;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let producer = SplitProducer {\n            data: self.data,\n            splitter: &self.splitter,\n        };\n        bridge_unindexed(producer, consumer)\n    }\n}\n\nstruct SplitProducer<'a, D, S> {\n    data: D,\n    splitter: &'a S,\n}\n\nimpl<'a, D, S> UnindexedProducer for SplitProducer<'a, D, S>\nwhere\n    D: Send,\n    S: Fn(D) -> (D, Option<D>) + Sync,\n{\n    type Item = D;\n\n    fn split(mut self) -> (Self, Option<Self>) {\n        let splitter = self.splitter;\n        let (left, right) = splitter(self.data);\n        self.data = left;\n        (self, right.map(|data| SplitProducer { data, splitter }))\n    }\n\n    fn fold_with<F>(self, folder: F) -> F\n    where\n        F: Folder<Self::Item>,\n    {\n        folder.consume(self.data)\n    }\n}\n"
  },
  {
    "path": "src/iter/step_by.rs",
    "content": "use super::plumbing::*;\nuse super::*;\nuse std::iter;\n\n/// `StepBy` is an iterator that skips `n` elements between each yield, where `n` is the given step.\n/// This struct is created by the [`step_by()`] method on [`IndexedParallelIterator`]\n///\n/// [`step_by()`]: IndexedParallelIterator::step_by()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\npub struct StepBy<I> {\n    base: I,\n    step: usize,\n}\n\nimpl<I> StepBy<I> {\n    /// Creates a new `StepBy` iterator.\n    pub(super) fn new(base: I, step: usize) -> Self {\n        StepBy { base, step }\n    }\n}\n\nimpl<I> ParallelIterator for StepBy<I>\nwhere\n    I: IndexedParallelIterator,\n{\n    type Item = I::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<I> IndexedParallelIterator for StepBy<I>\nwhere\n    I: IndexedParallelIterator,\n{\n    fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.base.len().div_ceil(self.step)\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        let len = self.base.len();\n        return self.base.with_producer(Callback {\n            callback,\n            step: self.step,\n            len,\n        });\n\n        struct Callback<CB> {\n            callback: CB,\n            step: usize,\n            len: usize,\n        }\n\n        impl<T, CB> ProducerCallback<T> for Callback<CB>\n        where\n            CB: ProducerCallback<T>,\n        {\n            type Output = CB::Output;\n            fn callback<P>(self, base: P) -> CB::Output\n            where\n                P: Producer<Item = T>,\n            {\n                let producer = StepByProducer {\n                    base,\n                    step: self.step,\n                    len: self.len,\n                };\n                self.callback.callback(producer)\n            }\n        }\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Producer implementation\n\nstruct StepByProducer<P> {\n    base: P,\n    step: usize,\n    len: usize,\n}\n\nimpl<P> Producer for StepByProducer<P>\nwhere\n    P: Producer,\n{\n    type Item = P::Item;\n    type IntoIter = iter::StepBy<P::IntoIter>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.base.into_iter().step_by(self.step)\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let elem_index = Ord::min(index * self.step, self.len);\n\n        let (left, right) = self.base.split_at(elem_index);\n        (\n            StepByProducer {\n                base: left,\n                step: self.step,\n                len: elem_index,\n            },\n            StepByProducer {\n                base: right,\n                step: self.step,\n                len: self.len - elem_index,\n            },\n        )\n    }\n\n    fn min_len(&self) -> usize {\n        self.base.min_len().div_ceil(self.step)\n    }\n\n    fn max_len(&self) -> usize {\n        self.base.max_len() / self.step\n    }\n}\n"
  },
  {
    "path": "src/iter/sum.rs",
    "content": "use super::plumbing::*;\nuse super::ParallelIterator;\n\nuse std::iter::{self, Sum};\nuse std::marker::PhantomData;\n\npub(super) fn sum<PI, S>(pi: PI) -> S\nwhere\n    PI: ParallelIterator,\n    S: Send + Sum<PI::Item> + Sum,\n{\n    pi.drive_unindexed(SumConsumer::new())\n}\n\nfn add<T: Sum>(left: T, right: T) -> T {\n    [left, right].into_iter().sum()\n}\n\nstruct SumConsumer<S: Send> {\n    _marker: PhantomData<*const S>,\n}\n\nunsafe impl<S: Send> Send for SumConsumer<S> {}\n\nimpl<S: Send> SumConsumer<S> {\n    fn new() -> SumConsumer<S> {\n        SumConsumer {\n            _marker: PhantomData,\n        }\n    }\n}\n\nimpl<S, T> Consumer<T> for SumConsumer<S>\nwhere\n    S: Send + Sum<T> + Sum,\n{\n    type Folder = SumFolder<S>;\n    type Reducer = Self;\n    type Result = S;\n\n    fn split_at(self, _index: usize) -> (Self, Self, Self) {\n        (SumConsumer::new(), SumConsumer::new(), SumConsumer::new())\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        SumFolder {\n            sum: iter::empty::<T>().sum(),\n        }\n    }\n\n    fn full(&self) -> bool {\n        false\n    }\n}\n\nimpl<S, T> UnindexedConsumer<T> for SumConsumer<S>\nwhere\n    S: Send + Sum<T> + Sum,\n{\n    fn split_off_left(&self) -> Self {\n        SumConsumer::new()\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        SumConsumer::new()\n    }\n}\n\nimpl<S> Reducer<S> for SumConsumer<S>\nwhere\n    S: Send + Sum,\n{\n    fn reduce(self, left: S, right: S) -> S {\n        add(left, right)\n    }\n}\n\nstruct SumFolder<S> {\n    sum: S,\n}\n\nimpl<S, T> Folder<T> for SumFolder<S>\nwhere\n    S: Sum<T> + Sum,\n{\n    type Result = S;\n\n    fn consume(self, item: T) -> Self {\n        SumFolder {\n            sum: add(self.sum, iter::once(item).sum()),\n        }\n    }\n\n    fn consume_iter<I>(self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = T>,\n    {\n        SumFolder {\n            sum: add(self.sum, iter.into_iter().sum()),\n        }\n    }\n\n    fn complete(self) -> S {\n        self.sum\n    }\n\n    fn full(&self) -> bool {\n        false\n    }\n}\n"
  },
  {
    "path": "src/iter/take.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\n/// `Take` is an iterator that iterates over the first `n` elements.\n/// This struct is created by the [`take()`] method on [`IndexedParallelIterator`]\n///\n/// [`take()`]: IndexedParallelIterator::take()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\npub struct Take<I> {\n    base: I,\n    n: usize,\n}\n\nimpl<I> Take<I>\nwhere\n    I: IndexedParallelIterator,\n{\n    /// Creates a new `Take` iterator.\n    pub(super) fn new(base: I, n: usize) -> Self {\n        let n = Ord::min(base.len(), n);\n        Take { base, n }\n    }\n}\n\nimpl<I> ParallelIterator for Take<I>\nwhere\n    I: IndexedParallelIterator,\n{\n    type Item = I::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<I> IndexedParallelIterator for Take<I>\nwhere\n    I: IndexedParallelIterator,\n{\n    fn len(&self) -> usize {\n        self.n\n    }\n\n    fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result {\n        bridge(self, consumer)\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        return self.base.with_producer(Callback {\n            callback,\n            n: self.n,\n        });\n\n        struct Callback<CB> {\n            callback: CB,\n            n: usize,\n        }\n\n        impl<T, CB> ProducerCallback<T> for Callback<CB>\n        where\n            CB: ProducerCallback<T>,\n        {\n            type Output = CB::Output;\n            fn callback<P>(self, base: P) -> CB::Output\n            where\n                P: Producer<Item = T>,\n            {\n                let (producer, _) = base.split_at(self.n);\n                self.callback.callback(producer)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/iter/take_any.rs",
    "content": "use super::plumbing::*;\nuse super::*;\nuse std::sync::atomic::{AtomicUsize, Ordering};\n\n/// `TakeAny` is an iterator that iterates over `n` elements from anywhere in `I`.\n/// This struct is created by the [`take_any()`] method on [`ParallelIterator`]\n///\n/// [`take_any()`]: ParallelIterator::take_any()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Clone, Debug)]\npub struct TakeAny<I> {\n    base: I,\n    count: usize,\n}\n\nimpl<I> TakeAny<I> {\n    /// Creates a new `TakeAny` iterator.\n    pub(super) fn new(base: I, count: usize) -> Self {\n        TakeAny { base, count }\n    }\n}\n\nimpl<I> ParallelIterator for TakeAny<I>\nwhere\n    I: ParallelIterator,\n{\n    type Item = I::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer1 = TakeAnyConsumer {\n            base: consumer,\n            count: &AtomicUsize::new(self.count),\n        };\n        self.base.drive_unindexed(consumer1)\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Consumer implementation\n\nstruct TakeAnyConsumer<'f, C> {\n    base: C,\n    count: &'f AtomicUsize,\n}\n\nimpl<'f, T, C> Consumer<T> for TakeAnyConsumer<'f, C>\nwhere\n    C: Consumer<T>,\n    T: Send,\n{\n    type Folder = TakeAnyFolder<'f, C::Folder>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            TakeAnyConsumer { base: left, ..self },\n            TakeAnyConsumer {\n                base: right,\n                ..self\n            },\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        TakeAnyFolder {\n            base: self.base.into_folder(),\n            count: self.count,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.count.load(Ordering::Relaxed) == 0 || self.base.full()\n    }\n}\n\nimpl<'f, T, C> UnindexedConsumer<T> for TakeAnyConsumer<'f, C>\nwhere\n    C: UnindexedConsumer<T>,\n    T: Send,\n{\n    fn split_off_left(&self) -> Self {\n        TakeAnyConsumer {\n            base: self.base.split_off_left(),\n            ..*self\n        }\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n\nstruct TakeAnyFolder<'f, C> {\n    base: C,\n    count: &'f AtomicUsize,\n}\n\nfn checked_decrement(u: &AtomicUsize) -> bool {\n    u.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |u| u.checked_sub(1))\n        .is_ok()\n}\n\nimpl<'f, T, C> Folder<T> for TakeAnyFolder<'f, C>\nwhere\n    C: Folder<T>,\n{\n    type Result = C::Result;\n\n    fn consume(mut self, item: T) -> Self {\n        if checked_decrement(self.count) {\n            self.base = self.base.consume(item);\n        }\n        self\n    }\n\n    fn consume_iter<I>(mut self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = T>,\n    {\n        self.base = self.base.consume_iter(\n            iter.into_iter()\n                .take_while(move |_| checked_decrement(self.count)),\n        );\n        self\n    }\n\n    fn complete(self) -> C::Result {\n        self.base.complete()\n    }\n\n    fn full(&self) -> bool {\n        self.count.load(Ordering::Relaxed) == 0 || self.base.full()\n    }\n}\n"
  },
  {
    "path": "src/iter/take_any_while.rs",
    "content": "use super::plumbing::*;\nuse super::*;\nuse std::fmt;\nuse std::sync::atomic::{AtomicBool, Ordering};\n\n/// `TakeAnyWhile` is an iterator that iterates over elements from anywhere in `I`\n/// until the callback returns `false`.\n/// This struct is created by the [`take_any_while()`] method on [`ParallelIterator`]\n///\n/// [`take_any_while()`]: ParallelIterator::take_any_while()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Clone)]\npub struct TakeAnyWhile<I, P> {\n    base: I,\n    predicate: P,\n}\n\nimpl<I: fmt::Debug, P> fmt::Debug for TakeAnyWhile<I, P> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"TakeAnyWhile\")\n            .field(\"base\", &self.base)\n            .finish()\n    }\n}\n\nimpl<I, P> TakeAnyWhile<I, P> {\n    /// Creates a new `TakeAnyWhile` iterator.\n    pub(super) fn new(base: I, predicate: P) -> Self {\n        TakeAnyWhile { base, predicate }\n    }\n}\n\nimpl<I, P> ParallelIterator for TakeAnyWhile<I, P>\nwhere\n    I: ParallelIterator,\n    P: Fn(&I::Item) -> bool + Sync + Send,\n{\n    type Item = I::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer1 = TakeAnyWhileConsumer {\n            base: consumer,\n            predicate: &self.predicate,\n            taking: &AtomicBool::new(true),\n        };\n        self.base.drive_unindexed(consumer1)\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Consumer implementation\n\nstruct TakeAnyWhileConsumer<'p, C, P> {\n    base: C,\n    predicate: &'p P,\n    taking: &'p AtomicBool,\n}\n\nimpl<'p, T, C, P> Consumer<T> for TakeAnyWhileConsumer<'p, C, P>\nwhere\n    C: Consumer<T>,\n    P: Fn(&T) -> bool + Sync,\n{\n    type Folder = TakeAnyWhileFolder<'p, C::Folder, P>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            TakeAnyWhileConsumer { base: left, ..self },\n            TakeAnyWhileConsumer {\n                base: right,\n                ..self\n            },\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        TakeAnyWhileFolder {\n            base: self.base.into_folder(),\n            predicate: self.predicate,\n            taking: self.taking,\n        }\n    }\n\n    fn full(&self) -> bool {\n        !self.taking.load(Ordering::Relaxed) || self.base.full()\n    }\n}\n\nimpl<'p, T, C, P> UnindexedConsumer<T> for TakeAnyWhileConsumer<'p, C, P>\nwhere\n    C: UnindexedConsumer<T>,\n    P: Fn(&T) -> bool + Sync,\n{\n    fn split_off_left(&self) -> Self {\n        TakeAnyWhileConsumer {\n            base: self.base.split_off_left(),\n            ..*self\n        }\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n\nstruct TakeAnyWhileFolder<'p, C, P> {\n    base: C,\n    predicate: &'p P,\n    taking: &'p AtomicBool,\n}\n\nfn take<T>(item: &T, taking: &AtomicBool, predicate: &impl Fn(&T) -> bool) -> bool {\n    if !taking.load(Ordering::Relaxed) {\n        return false;\n    }\n    if predicate(item) {\n        return true;\n    }\n    taking.store(false, Ordering::Relaxed);\n    false\n}\n\nimpl<'p, T, C, P> Folder<T> for TakeAnyWhileFolder<'p, C, P>\nwhere\n    C: Folder<T>,\n    P: Fn(&T) -> bool + 'p,\n{\n    type Result = C::Result;\n\n    fn consume(mut self, item: T) -> Self {\n        if take(&item, self.taking, self.predicate) {\n            self.base = self.base.consume(item);\n        }\n        self\n    }\n\n    fn consume_iter<I>(mut self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = T>,\n    {\n        self.base = self.base.consume_iter(\n            iter.into_iter()\n                .take_while(move |x| take(x, self.taking, self.predicate)),\n        );\n        self\n    }\n\n    fn complete(self) -> C::Result {\n        self.base.complete()\n    }\n\n    fn full(&self) -> bool {\n        !self.taking.load(Ordering::Relaxed) || self.base.full()\n    }\n}\n"
  },
  {
    "path": "src/iter/test.rs",
    "content": "use std::sync::atomic::{AtomicUsize, Ordering};\n\nuse super::*;\nuse crate::prelude::*;\nuse rayon_core::*;\n\nuse rand::distr::StandardUniform;\nuse rand::{Rng, SeedableRng};\nuse rand_xorshift::XorShiftRng;\nuse std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};\nuse std::collections::{BinaryHeap, VecDeque};\nuse std::ffi::OsStr;\nuse std::fmt::Debug;\nuse std::sync::mpsc;\n\nfn is_indexed<T: IndexedParallelIterator>(_: T) {}\n\nfn seeded_rng() -> XorShiftRng {\n    let mut seed = <XorShiftRng as SeedableRng>::Seed::default();\n    (0..).zip(seed.as_mut()).for_each(|(i, x)| *x = i);\n    XorShiftRng::from_seed(seed)\n}\n\n#[test]\nfn execute() {\n    let a: Vec<i32> = (0..1024).collect();\n    let mut b = vec![];\n    a.par_iter().map(|&i| i + 1).collect_into_vec(&mut b);\n    let c: Vec<i32> = (0..1024).map(|i| i + 1).collect();\n    assert_eq!(b, c);\n}\n\n#[test]\nfn execute_cloned() {\n    let a: Vec<i32> = (0..1024).collect();\n    let mut b: Vec<i32> = vec![];\n    a.par_iter().cloned().collect_into_vec(&mut b);\n    let c: Vec<i32> = (0..1024).collect();\n    assert_eq!(b, c);\n}\n\n#[test]\nfn execute_range() {\n    let a = 0i32..1024;\n    let mut b = vec![];\n    a.into_par_iter().map(|i| i + 1).collect_into_vec(&mut b);\n    let c: Vec<i32> = (0..1024).map(|i| i + 1).collect();\n    assert_eq!(b, c);\n}\n\n#[test]\nfn execute_unindexed_range() {\n    let a = 0i64..1024;\n    let b: LinkedList<i64> = a.into_par_iter().map(|i| i + 1).collect();\n    let c: LinkedList<i64> = (0..1024).map(|i| i + 1).collect();\n    assert_eq!(b, c);\n}\n\n#[test]\nfn execute_pseudo_indexed_range() {\n    let range = i128::MAX - 1024..i128::MAX;\n\n    // Given `Some` length, collecting `Vec` will try to act indexed.\n    let a = range.clone().into_par_iter();\n    assert_eq!(a.opt_len(), Some(1024));\n\n    let b: Vec<i128> = a.map(|i| i + 1).collect();\n    let c: Vec<i128> = range.map(|i| i + 1).collect();\n    assert_eq!(b, c);\n}\n\n#[test]\nfn check_map_indexed() {\n    let a = [1, 2, 3];\n    is_indexed(a.par_iter().map(|x| x));\n}\n\n#[test]\nfn map_sum() {\n    let a: Vec<i32> = (0..1024).collect();\n    let r1: i32 = a.par_iter().map(|&i| i + 1).sum();\n    let r2 = a.iter().map(|&i| i + 1).sum();\n    assert_eq!(r1, r2);\n}\n\n#[test]\nfn map_reduce() {\n    let a: Vec<i32> = (0..1024).collect();\n    let r1 = a.par_iter().map(|&i| i + 1).reduce(|| 0, |i, j| i + j);\n    let r2 = a.iter().map(|&i| i + 1).sum();\n    assert_eq!(r1, r2);\n}\n\n#[test]\nfn map_reduce_with() {\n    let a: Vec<i32> = (0..1024).collect();\n    let r1 = a.par_iter().map(|&i| i + 1).reduce_with(|i, j| i + j);\n    let r2 = a.iter().map(|&i| i + 1).sum();\n    assert_eq!(r1, Some(r2));\n}\n\n#[test]\nfn fold_map_reduce() {\n    // Kind of a weird test, but it demonstrates various\n    // transformations that are taking place. Relies on\n    // `with_max_len(1).fold()` being equivalent to `map()`.\n    //\n    // Take each number from 0 to 32 and fold them by appending to a\n    // vector.  Because of `with_max_len(1)`, this will produce 32 vectors,\n    // each with one item.  We then collect all of these into an\n    // individual vector by mapping each into their own vector (so we\n    // have Vec<Vec<i32>>) and then reducing those into a single\n    // vector.\n    let r1 = (0_i32..32)\n        .into_par_iter()\n        .with_max_len(1)\n        .fold(Vec::new, |mut v, e| {\n            v.push(e);\n            v\n        })\n        .map(|v| vec![v])\n        .reduce_with(|mut v_a, v_b| {\n            v_a.extend(v_b);\n            v_a\n        });\n    assert_eq!(\n        r1,\n        Some(vec![\n            vec![0],\n            vec![1],\n            vec![2],\n            vec![3],\n            vec![4],\n            vec![5],\n            vec![6],\n            vec![7],\n            vec![8],\n            vec![9],\n            vec![10],\n            vec![11],\n            vec![12],\n            vec![13],\n            vec![14],\n            vec![15],\n            vec![16],\n            vec![17],\n            vec![18],\n            vec![19],\n            vec![20],\n            vec![21],\n            vec![22],\n            vec![23],\n            vec![24],\n            vec![25],\n            vec![26],\n            vec![27],\n            vec![28],\n            vec![29],\n            vec![30],\n            vec![31]\n        ])\n    );\n}\n\n#[test]\nfn fold_is_full() {\n    let counter = AtomicUsize::new(0);\n    let a = (0_i32..2048)\n        .into_par_iter()\n        .inspect(|_| {\n            counter.fetch_add(1, Ordering::SeqCst);\n        })\n        .fold(|| 0, |a, b| a + b)\n        .find_any(|_| true);\n    assert!(a.is_some());\n    assert!(counter.load(Ordering::SeqCst) < 2048); // should not have visited every single one\n}\n\n#[test]\nfn check_step_by() {\n    let a: Vec<i32> = (0..1024).step_by(2).collect();\n    let b: Vec<i32> = (0..1024).into_par_iter().step_by(2).collect();\n\n    assert_eq!(a, b);\n}\n\n#[test]\nfn check_step_by_unaligned() {\n    let a: Vec<i32> = (0..1029).step_by(10).collect();\n    let b: Vec<i32> = (0..1029).into_par_iter().step_by(10).collect();\n\n    assert_eq!(a, b)\n}\n\n#[test]\nfn check_step_by_rev() {\n    let a: Vec<i32> = (0..1024).step_by(2).rev().collect();\n    let b: Vec<i32> = (0..1024).into_par_iter().step_by(2).rev().collect();\n\n    assert_eq!(a, b);\n}\n\n#[test]\nfn check_enumerate() {\n    let a: Vec<usize> = (0..1024).rev().collect();\n\n    let mut b = vec![];\n    a.par_iter()\n        .enumerate()\n        .map(|(i, &x)| i + x)\n        .collect_into_vec(&mut b);\n    assert!(b.iter().all(|&x| x == a.len() - 1));\n}\n\n#[test]\nfn check_enumerate_rev() {\n    let a: Vec<usize> = (0..1024).rev().collect();\n\n    let mut b = vec![];\n    a.par_iter()\n        .enumerate()\n        .rev()\n        .map(|(i, &x)| i + x)\n        .collect_into_vec(&mut b);\n    assert!(b.iter().all(|&x| x == a.len() - 1));\n}\n\n#[test]\nfn check_indices_after_enumerate_split() {\n    let a: Vec<i32> = (0..1024).collect();\n    a.par_iter().enumerate().with_producer(WithProducer);\n\n    struct WithProducer;\n    impl<'a> ProducerCallback<(usize, &'a i32)> for WithProducer {\n        type Output = ();\n        fn callback<P>(self, producer: P)\n        where\n            P: Producer<Item = (usize, &'a i32)>,\n        {\n            let (a, b) = producer.split_at(512);\n            for ((index, value), trusted_index) in a.into_iter().zip(0..) {\n                assert_eq!(index, trusted_index);\n                assert_eq!(index, *value as usize);\n            }\n            for ((index, value), trusted_index) in b.into_iter().zip(512..) {\n                assert_eq!(index, trusted_index);\n                assert_eq!(index, *value as usize);\n            }\n        }\n    }\n}\n\n#[test]\nfn check_increment() {\n    let mut a: Vec<usize> = (0..1024).rev().collect();\n\n    a.par_iter_mut().enumerate().for_each(|(i, v)| *v += i);\n\n    assert!(a.iter().all(|&x| x == a.len() - 1));\n}\n\n#[test]\nfn check_skip() {\n    let a: Vec<usize> = (0..1024).collect();\n\n    let mut v1 = Vec::new();\n    a.par_iter().skip(16).collect_into_vec(&mut v1);\n    let v2 = a.iter().skip(16).collect::<Vec<_>>();\n    assert_eq!(v1, v2);\n\n    let mut v1 = Vec::new();\n    a.par_iter().skip(2048).collect_into_vec(&mut v1);\n    let v2 = a.iter().skip(2048).collect::<Vec<_>>();\n    assert_eq!(v1, v2);\n\n    let mut v1 = Vec::new();\n    a.par_iter().skip(0).collect_into_vec(&mut v1);\n    #[allow(clippy::iter_skip_zero)]\n    let v2 = a.iter().skip(0).collect::<Vec<_>>();\n    assert_eq!(v1, v2);\n\n    // Check that the skipped elements side effects are executed\n    use std::sync::atomic::{AtomicUsize, Ordering};\n    let num = AtomicUsize::new(0);\n    a.par_iter()\n        .map(|&n| num.fetch_add(n, Ordering::Relaxed))\n        .skip(512)\n        .count();\n    assert_eq!(num.load(Ordering::Relaxed), a.iter().sum::<usize>());\n}\n\n#[test]\nfn check_take() {\n    let a: Vec<usize> = (0..1024).collect();\n\n    let mut v1 = Vec::new();\n    a.par_iter().take(16).collect_into_vec(&mut v1);\n    let v2 = a.iter().take(16).collect::<Vec<_>>();\n    assert_eq!(v1, v2);\n\n    let mut v1 = Vec::new();\n    a.par_iter().take(2048).collect_into_vec(&mut v1);\n    let v2 = a.iter().take(2048).collect::<Vec<_>>();\n    assert_eq!(v1, v2);\n\n    let mut v1 = Vec::new();\n    a.par_iter().take(0).collect_into_vec(&mut v1);\n    let v2 = a.iter().take(0).collect::<Vec<_>>();\n    assert_eq!(v1, v2);\n}\n\n#[test]\nfn check_inspect() {\n    use std::sync::atomic::{AtomicUsize, Ordering};\n\n    let a = AtomicUsize::new(0);\n    let b: usize = (0_usize..1024)\n        .into_par_iter()\n        .inspect(|&i| {\n            a.fetch_add(i, Ordering::Relaxed);\n        })\n        .sum();\n\n    assert_eq!(a.load(Ordering::Relaxed), b);\n}\n\n#[test]\nfn check_move() {\n    let a = vec![vec![1, 2, 3]];\n    let ptr = a[0].as_ptr();\n\n    let mut b = vec![];\n    a.into_par_iter().collect_into_vec(&mut b);\n\n    // a simple move means the inner vec will be completely unchanged\n    assert_eq!(ptr, b[0].as_ptr());\n}\n\n#[test]\nfn check_drops() {\n    use std::sync::atomic::{AtomicUsize, Ordering};\n\n    let c = AtomicUsize::new(0);\n    let a = vec![DropCounter(&c); 10];\n\n    let mut b = vec![];\n    a.clone().into_par_iter().collect_into_vec(&mut b);\n    assert_eq!(c.load(Ordering::Relaxed), 0);\n\n    b.into_par_iter();\n    assert_eq!(c.load(Ordering::Relaxed), 10);\n\n    a.into_par_iter().with_producer(Partial);\n    assert_eq!(c.load(Ordering::Relaxed), 20);\n\n    #[derive(Clone)]\n    struct DropCounter<'a>(&'a AtomicUsize);\n    impl<'a> Drop for DropCounter<'a> {\n        fn drop(&mut self) {\n            self.0.fetch_add(1, Ordering::Relaxed);\n        }\n    }\n\n    struct Partial;\n    impl<'a> ProducerCallback<DropCounter<'a>> for Partial {\n        type Output = ();\n        fn callback<P>(self, producer: P)\n        where\n            P: Producer<Item = DropCounter<'a>>,\n        {\n            let (a, _) = producer.split_at(5);\n            a.into_iter().next();\n        }\n    }\n}\n\n#[test]\nfn check_slice_indexed() {\n    let a = vec![1, 2, 3];\n    is_indexed(a.par_iter());\n}\n\n#[test]\nfn check_slice_mut_indexed() {\n    let mut a = vec![1, 2, 3];\n    is_indexed(a.par_iter_mut());\n}\n\n#[test]\nfn check_vec_indexed() {\n    let a = vec![1, 2, 3];\n    is_indexed(a.into_par_iter());\n}\n\n#[test]\nfn check_range_indexed() {\n    is_indexed((1..5).into_par_iter());\n}\n\n#[test]\nfn check_cmp_direct() {\n    let a = (0..1024).into_par_iter();\n    let b = (0..1024).into_par_iter();\n\n    let result = a.cmp(b);\n\n    assert!(result == ::std::cmp::Ordering::Equal);\n}\n\n#[test]\nfn check_cmp_to_seq() {\n    assert_eq!(\n        (0..1024).into_par_iter().cmp(0..1024),\n        (0..1024).cmp(0..1024)\n    );\n}\n\n#[test]\nfn check_cmp_rng_to_seq() {\n    let mut rng = seeded_rng();\n    let rng = &mut rng;\n    let a: Vec<i32> = rng.sample_iter(&StandardUniform).take(1024).collect();\n    let b: Vec<i32> = rng.sample_iter(&StandardUniform).take(1024).collect();\n    for i in 0..a.len() {\n        let par_result = a[i..].par_iter().cmp(b[i..].par_iter());\n        let seq_result = a[i..].iter().cmp(b[i..].iter());\n\n        assert_eq!(par_result, seq_result);\n    }\n}\n\n#[test]\nfn check_cmp_lt_direct() {\n    let a = (0..1024).into_par_iter();\n    let b = (1..1024).into_par_iter();\n\n    let result = a.cmp(b);\n\n    assert!(result == ::std::cmp::Ordering::Less);\n}\n\n#[test]\nfn check_cmp_lt_to_seq() {\n    assert_eq!(\n        (0..1024).into_par_iter().cmp(1..1024),\n        (0..1024).cmp(1..1024)\n    )\n}\n\n#[test]\nfn check_cmp_gt_direct() {\n    let a = (1..1024).into_par_iter();\n    let b = (0..1024).into_par_iter();\n\n    let result = a.cmp(b);\n\n    assert!(result == ::std::cmp::Ordering::Greater);\n}\n\n#[test]\nfn check_cmp_gt_to_seq() {\n    assert_eq!(\n        (1..1024).into_par_iter().cmp(0..1024),\n        (1..1024).cmp(0..1024)\n    )\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn check_cmp_short_circuit() {\n    // We only use a single thread in order to make the short-circuit behavior deterministic.\n    let pool = ThreadPoolBuilder::new().num_threads(1).build().unwrap();\n\n    let a = vec![0; 1024];\n    let mut b = a.clone();\n    b[42] = 1;\n\n    pool.install(|| {\n        let expected = ::std::cmp::Ordering::Less;\n        assert_eq!(a.par_iter().cmp(&b), expected);\n\n        for len in 1..10 {\n            let counter = AtomicUsize::new(0);\n            let result = a\n                .par_iter()\n                .with_max_len(len)\n                .inspect(|_| {\n                    counter.fetch_add(1, Ordering::SeqCst);\n                })\n                .cmp(&b);\n            assert_eq!(result, expected);\n            // should not have visited every single one\n            assert!(counter.into_inner() < a.len());\n        }\n    });\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn check_partial_cmp_short_circuit() {\n    // We only use a single thread to make the short-circuit behavior deterministic.\n    let pool = ThreadPoolBuilder::new().num_threads(1).build().unwrap();\n\n    let a = vec![0; 1024];\n    let mut b = a.clone();\n    b[42] = 1;\n\n    pool.install(|| {\n        let expected = Some(::std::cmp::Ordering::Less);\n        assert_eq!(a.par_iter().partial_cmp(&b), expected);\n\n        for len in 1..10 {\n            let counter = AtomicUsize::new(0);\n            let result = a\n                .par_iter()\n                .with_max_len(len)\n                .inspect(|_| {\n                    counter.fetch_add(1, Ordering::SeqCst);\n                })\n                .partial_cmp(&b);\n            assert_eq!(result, expected);\n            // should not have visited every single one\n            assert!(counter.into_inner() < a.len());\n        }\n    });\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn check_partial_cmp_nan_short_circuit() {\n    // We only use a single thread to make the short-circuit behavior deterministic.\n    let pool = ThreadPoolBuilder::new().num_threads(1).build().unwrap();\n\n    let a = vec![0.0; 1024];\n    let mut b = a.clone();\n    b[42] = f64::NAN;\n\n    pool.install(|| {\n        let expected = None;\n        assert_eq!(a.par_iter().partial_cmp(&b), expected);\n\n        for len in 1..10 {\n            let counter = AtomicUsize::new(0);\n            let result = a\n                .par_iter()\n                .with_max_len(len)\n                .inspect(|_| {\n                    counter.fetch_add(1, Ordering::SeqCst);\n                })\n                .partial_cmp(&b);\n            assert_eq!(result, expected);\n            // should not have visited every single one\n            assert!(counter.into_inner() < a.len());\n        }\n    });\n}\n\n#[test]\nfn check_partial_cmp_direct() {\n    let a = (0..1024).into_par_iter();\n    let b = (0..1024).into_par_iter();\n\n    let result = a.partial_cmp(b);\n\n    assert!(result == Some(::std::cmp::Ordering::Equal));\n}\n\n#[test]\nfn check_partial_cmp_to_seq() {\n    let par_result = (0..1024).into_par_iter().partial_cmp(0..1024);\n    let seq_result = (0..1024).partial_cmp(0..1024);\n    assert_eq!(par_result, seq_result);\n}\n\n#[test]\nfn check_partial_cmp_rng_to_seq() {\n    let mut rng = seeded_rng();\n    let rng = &mut rng;\n    let a: Vec<i32> = rng.sample_iter(&StandardUniform).take(1024).collect();\n    let b: Vec<i32> = rng.sample_iter(&StandardUniform).take(1024).collect();\n    for i in 0..a.len() {\n        let par_result = a[i..].par_iter().partial_cmp(b[i..].par_iter());\n        let seq_result = a[i..].iter().partial_cmp(b[i..].iter());\n\n        assert_eq!(par_result, seq_result);\n    }\n}\n\n#[test]\nfn check_partial_cmp_lt_direct() {\n    let a = (0..1024).into_par_iter();\n    let b = (1..1024).into_par_iter();\n\n    let result = a.partial_cmp(b);\n\n    assert!(result == Some(::std::cmp::Ordering::Less));\n}\n\n#[test]\nfn check_partial_cmp_lt_to_seq() {\n    let par_result = (0..1024).into_par_iter().partial_cmp(1..1024);\n    let seq_result = (0..1024).partial_cmp(1..1024);\n    assert_eq!(par_result, seq_result);\n}\n\n#[test]\nfn check_partial_cmp_gt_direct() {\n    let a = (1..1024).into_par_iter();\n    let b = (0..1024).into_par_iter();\n\n    let result = a.partial_cmp(b);\n\n    assert!(result == Some(::std::cmp::Ordering::Greater));\n}\n\n#[test]\nfn check_partial_cmp_gt_to_seq() {\n    let par_result = (1..1024).into_par_iter().partial_cmp(0..1024);\n    let seq_result = (1..1024).partial_cmp(0..1024);\n    assert_eq!(par_result, seq_result);\n}\n\n#[test]\nfn check_partial_cmp_none_direct() {\n    let a = vec![f64::NAN, 0.0];\n    let b = vec![0.0, 1.0];\n\n    let result = a.par_iter().partial_cmp(b.par_iter());\n\n    assert!(result.is_none());\n}\n\n#[test]\nfn check_partial_cmp_none_to_seq() {\n    let a = vec![f64::NAN, 0.0];\n    let b = vec![0.0, 1.0];\n\n    let par_result = a.par_iter().partial_cmp(b.par_iter());\n    let seq_result = a.iter().partial_cmp(b.iter());\n\n    assert_eq!(par_result, seq_result);\n}\n\n#[test]\nfn check_partial_cmp_late_nan_direct() {\n    let a = vec![0.0, f64::NAN];\n    let b = vec![1.0, 1.0];\n\n    let result = a.par_iter().partial_cmp(b.par_iter());\n\n    assert!(result == Some(::std::cmp::Ordering::Less));\n}\n\n#[test]\nfn check_partial_cmp_late_nan_to_seq() {\n    let a = vec![0.0, f64::NAN];\n    let b = vec![1.0, 1.0];\n\n    let par_result = a.par_iter().partial_cmp(b.par_iter());\n    let seq_result = a.iter().partial_cmp(b.iter());\n\n    assert_eq!(par_result, seq_result);\n}\n\n#[test]\nfn check_cmp_lengths() {\n    // comparisons should consider length if they are otherwise equal\n    let a = vec![0; 1024];\n    let b = vec![0; 1025];\n\n    assert_eq!(a.par_iter().cmp(&b), a.iter().cmp(&b));\n    assert_eq!(a.par_iter().partial_cmp(&b), a.iter().partial_cmp(&b));\n}\n\n#[test]\nfn check_eq_direct() {\n    let a = (0..1024).into_par_iter();\n    let b = (0..1024).into_par_iter();\n\n    let result = a.eq(b);\n\n    assert!(result);\n}\n\n#[test]\nfn check_eq_to_seq() {\n    let par_result = (0..1024).into_par_iter().eq((0..1024).into_par_iter());\n    let seq_result = (0..1024).eq(0..1024);\n\n    assert_eq!(par_result, seq_result);\n}\n\n#[test]\nfn check_ne_direct() {\n    let a = (0..1024).into_par_iter();\n    let b = (1..1024).into_par_iter();\n\n    let result = a.ne(b);\n\n    assert!(result);\n}\n\n#[test]\nfn check_ne_to_seq() {\n    let par_result = (0..1024).into_par_iter().ne((1..1025).into_par_iter());\n    let seq_result = (0..1024).ne(1..1025);\n\n    assert_eq!(par_result, seq_result);\n}\n\n#[test]\nfn check_ne_lengths() {\n    // equality should consider length too\n    let a = vec![0; 1024];\n    let b = vec![0; 1025];\n\n    assert_eq!(a.par_iter().eq(&b), a.iter().eq(&b));\n    assert_eq!(a.par_iter().ne(&b), a.iter().ne(&b));\n}\n\n#[test]\nfn check_lt_direct() {\n    assert!((0..1024).into_par_iter().lt(1..1024));\n    assert!(!(1..1024).into_par_iter().lt(0..1024));\n}\n\n#[test]\nfn check_lt_to_seq() {\n    let par_result = (0..1024).into_par_iter().lt((1..1024).into_par_iter());\n    let seq_result = (0..1024).lt(1..1024);\n\n    assert_eq!(par_result, seq_result);\n}\n\n#[test]\nfn check_le_equal_direct() {\n    assert!((0..1024).into_par_iter().le((0..1024).into_par_iter()));\n}\n\n#[test]\nfn check_le_equal_to_seq() {\n    let par_result = (0..1024).into_par_iter().le((0..1024).into_par_iter());\n    let seq_result = (0..1024).le(0..1024);\n\n    assert_eq!(par_result, seq_result);\n}\n\n#[test]\nfn check_le_less_direct() {\n    assert!((0..1024).into_par_iter().le((1..1024).into_par_iter()));\n}\n\n#[test]\nfn check_le_less_to_seq() {\n    let par_result = (0..1024).into_par_iter().le((1..1024).into_par_iter());\n    let seq_result = (0..1024).le(1..1024);\n\n    assert_eq!(par_result, seq_result);\n}\n\n#[test]\nfn check_gt_direct() {\n    assert!((1..1024).into_par_iter().gt((0..1024).into_par_iter()));\n}\n\n#[test]\nfn check_gt_to_seq() {\n    let par_result = (1..1024).into_par_iter().gt((0..1024).into_par_iter());\n    let seq_result = (1..1024).gt(0..1024);\n\n    assert_eq!(par_result, seq_result);\n}\n\n#[test]\nfn check_ge_equal_direct() {\n    assert!((0..1024).into_par_iter().ge((0..1024).into_par_iter()));\n}\n\n#[test]\nfn check_ge_equal_to_seq() {\n    let par_result = (0..1024).into_par_iter().ge((0..1024).into_par_iter());\n    let seq_result = (0..1024).ge(0..1024);\n\n    assert_eq!(par_result, seq_result);\n}\n\n#[test]\nfn check_ge_greater_direct() {\n    assert!((1..1024).into_par_iter().ge((0..1024).into_par_iter()));\n}\n\n#[test]\nfn check_ge_greater_to_seq() {\n    let par_result = (1..1024).into_par_iter().ge((0..1024).into_par_iter());\n    let seq_result = (1..1024).ge(0..1024);\n\n    assert_eq!(par_result, seq_result);\n}\n\n#[test]\nfn check_zip() {\n    let mut a: Vec<usize> = (0..1024).rev().collect();\n    let b: Vec<usize> = (0..1024).collect();\n\n    a.par_iter_mut().zip(&b[..]).for_each(|(a, &b)| *a += b);\n\n    assert!(a.iter().all(|&x| x == a.len() - 1));\n}\n\n#[test]\nfn check_zip_into_par_iter() {\n    let mut a: Vec<usize> = (0..1024).rev().collect();\n    let b: Vec<usize> = (0..1024).collect();\n\n    a.par_iter_mut()\n        .zip(&b) // here we rely on &b iterating over &usize\n        .for_each(|(a, &b)| *a += b);\n\n    assert!(a.iter().all(|&x| x == a.len() - 1));\n}\n\n#[test]\nfn check_zip_into_mut_par_iter() {\n    let a: Vec<usize> = (0..1024).rev().collect();\n    let mut b: Vec<usize> = (0..1024).collect();\n\n    a.par_iter().zip(&mut b).for_each(|(&a, b)| *b += a);\n\n    assert!(b.iter().all(|&x| x == b.len() - 1));\n}\n\n#[test]\nfn check_zip_range() {\n    let mut a: Vec<usize> = (0..1024).rev().collect();\n\n    a.par_iter_mut()\n        .zip(0usize..1024)\n        .for_each(|(a, b)| *a += b);\n\n    assert!(a.iter().all(|&x| x == a.len() - 1));\n}\n\n#[test]\nfn check_zip_eq() {\n    let mut a: Vec<usize> = (0..1024).rev().collect();\n    let b: Vec<usize> = (0..1024).collect();\n\n    a.par_iter_mut().zip_eq(&b[..]).for_each(|(a, &b)| *a += b);\n\n    assert!(a.iter().all(|&x| x == a.len() - 1));\n}\n\n#[test]\nfn check_zip_eq_into_par_iter() {\n    let mut a: Vec<usize> = (0..1024).rev().collect();\n    let b: Vec<usize> = (0..1024).collect();\n\n    a.par_iter_mut()\n        .zip_eq(&b) // here we rely on &b iterating over &usize\n        .for_each(|(a, &b)| *a += b);\n\n    assert!(a.iter().all(|&x| x == a.len() - 1));\n}\n\n#[test]\nfn check_zip_eq_into_mut_par_iter() {\n    let a: Vec<usize> = (0..1024).rev().collect();\n    let mut b: Vec<usize> = (0..1024).collect();\n\n    a.par_iter().zip_eq(&mut b).for_each(|(&a, b)| *b += a);\n\n    assert!(b.iter().all(|&x| x == b.len() - 1));\n}\n\n#[test]\nfn check_zip_eq_range() {\n    let mut a: Vec<usize> = (0..1024).rev().collect();\n\n    a.par_iter_mut()\n        .zip_eq(0usize..1024)\n        .for_each(|(a, b)| *a += b);\n\n    assert!(a.iter().all(|&x| x == a.len() - 1));\n}\n\n#[test]\nfn check_sum_filtered_ints() {\n    let a: Vec<i32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n    let par_sum_evens: i32 = a.par_iter().filter(|&x| (x & 1) == 0).sum();\n    let seq_sum_evens = a.iter().filter(|&x| (x & 1) == 0).sum();\n    assert_eq!(par_sum_evens, seq_sum_evens);\n}\n\n#[test]\nfn check_sum_filtermap_ints() {\n    let a: Vec<i32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n    let par_sum_evens: u32 = a\n        .par_iter()\n        .filter_map(|&x| if (x & 1) == 0 { Some(x as u32) } else { None })\n        .sum();\n    let seq_sum_evens = a\n        .iter()\n        .filter_map(|&x| if (x & 1) == 0 { Some(x as u32) } else { None })\n        .sum();\n    assert_eq!(par_sum_evens, seq_sum_evens);\n}\n\n#[test]\nfn check_flat_map_nested_ranges() {\n    // FIXME -- why are precise type hints required on the integers here?\n\n    let v: i32 = (0_i32..10)\n        .into_par_iter()\n        .flat_map(|i| (0_i32..10).into_par_iter().map(move |j| (i, j)))\n        .map(|(i, j)| i * j)\n        .sum();\n\n    let w = (0_i32..10)\n        .flat_map(|i| (0_i32..10).map(move |j| (i, j)))\n        .map(|(i, j)| i * j)\n        .sum();\n\n    assert_eq!(v, w);\n}\n\n#[test]\nfn check_empty_flat_map_sum() {\n    let a: Vec<i32> = (0..1024).collect();\n    let empty = &a[..0];\n\n    // empty on the inside\n    let b: i32 = a.par_iter().flat_map(|_| empty).sum();\n    assert_eq!(b, 0);\n\n    // empty on the outside\n    let c: i32 = empty.par_iter().flat_map(|_| a.par_iter()).sum();\n    assert_eq!(c, 0);\n}\n\n#[test]\nfn check_flatten_vec() {\n    let a: Vec<i32> = (0..1024).collect();\n    let b: Vec<Vec<i32>> = vec![a.clone(), a.clone(), a.clone(), a.clone()];\n    let c: Vec<i32> = b.par_iter().flatten().cloned().collect();\n    let mut d = a.clone();\n    d.extend(&a);\n    d.extend(&a);\n    d.extend(&a);\n\n    assert_eq!(d, c);\n}\n\n#[test]\nfn check_flatten_vec_empty() {\n    let a: Vec<Vec<i32>> = vec![vec![]];\n    let b: Vec<i32> = a.par_iter().flatten().cloned().collect();\n\n    assert_eq!(vec![] as Vec<i32>, b);\n}\n\n#[test]\nfn check_slice_split() {\n    let v: Vec<_> = (0..1000).collect();\n    for m in 1..100 {\n        let a: Vec<_> = v.split(|x| x % m == 0).collect();\n        let b: Vec<_> = v.par_split(|x| x % m == 0).collect();\n        assert_eq!(a, b);\n    }\n\n    // same as std::slice::split() examples\n    let slice = [10, 40, 33, 20];\n    let v: Vec<_> = slice.par_split(|num| num % 3 == 0).collect();\n    assert_eq!(v, &[&slice[..2], &slice[3..]]);\n\n    let slice = [10, 40, 33];\n    let v: Vec<_> = slice.par_split(|num| num % 3 == 0).collect();\n    assert_eq!(v, &[&slice[..2], &slice[..0]]);\n\n    let slice = [10, 6, 33, 20];\n    let v: Vec<_> = slice.par_split(|num| num % 3 == 0).collect();\n    assert_eq!(v, &[&slice[..1], &slice[..0], &slice[3..]]);\n}\n\n#[test]\nfn check_slice_split_inclusive() {\n    let v: Vec<_> = (0..1000).collect();\n    for m in 1..100 {\n        let a: Vec<_> = v.split_inclusive(|x| x % m == 0).collect();\n        let b: Vec<_> = v.par_split_inclusive(|x| x % m == 0).collect();\n        assert_eq!(a, b);\n    }\n\n    // same as std::slice::split_inclusive() examples\n    let slice = [10, 40, 33, 20];\n    let v: Vec<_> = slice.par_split_inclusive(|num| num % 3 == 0).collect();\n    assert_eq!(v, &[&slice[..3], &slice[3..]]);\n\n    let slice = [3, 10, 40, 33];\n    let v: Vec<_> = slice.par_split_inclusive(|num| num % 3 == 0).collect();\n    assert_eq!(v, &[&slice[..1], &slice[1..]]);\n}\n\n#[test]\nfn check_slice_split_mut() {\n    let mut v1: Vec<_> = (0..1000).collect();\n    let mut v2 = v1.clone();\n    for m in 1..100 {\n        let a: Vec<_> = v1.split_mut(|x| x % m == 0).collect();\n        let b: Vec<_> = v2.par_split_mut(|x| x % m == 0).collect();\n        assert_eq!(a, b);\n    }\n\n    // same as std::slice::split_mut() example\n    let mut v = [10, 40, 30, 20, 60, 50];\n    v.par_split_mut(|num| num % 3 == 0).for_each(|group| {\n        group[0] = 1;\n    });\n    assert_eq!(v, [1, 40, 30, 1, 60, 1]);\n}\n\n#[test]\nfn check_slice_split_inclusive_mut() {\n    let mut v1: Vec<_> = (0..1000).collect();\n    let mut v2 = v1.clone();\n    for m in 1..100 {\n        let a: Vec<_> = v1.split_inclusive_mut(|x| x % m == 0).collect();\n        let b: Vec<_> = v2.par_split_inclusive_mut(|x| x % m == 0).collect();\n        assert_eq!(a, b);\n    }\n\n    // same as std::slice::split_inclusive_mut() example\n    let mut v = [10, 40, 30, 20, 60, 50];\n    v.par_split_inclusive_mut(|num| num % 3 == 0)\n        .for_each(|group| {\n            let terminator_idx = group.len() - 1;\n            group[terminator_idx] = 1;\n        });\n    assert_eq!(v, [10, 40, 1, 20, 1, 1]);\n}\n\n#[test]\nfn check_chunks() {\n    let a: Vec<i32> = vec![1, 5, 10, 4, 100, 3, 1000, 2, 10000, 1];\n    let par_sum_product_pairs: i32 = a.par_chunks(2).map(|c| c.iter().product::<i32>()).sum();\n    let seq_sum_product_pairs = a.chunks(2).map(|c| c.iter().product::<i32>()).sum();\n    assert_eq!(par_sum_product_pairs, 12345);\n    assert_eq!(par_sum_product_pairs, seq_sum_product_pairs);\n\n    let par_sum_product_triples: i32 = a.par_chunks(3).map(|c| c.iter().product::<i32>()).sum();\n    let seq_sum_product_triples = a.chunks(3).map(|c| c.iter().product::<i32>()).sum();\n    assert_eq!(par_sum_product_triples, 5_0 + 12_00 + 20_000_000 + 1);\n    assert_eq!(par_sum_product_triples, seq_sum_product_triples);\n}\n\n#[test]\nfn check_chunks_mut() {\n    let mut a: Vec<i32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n    let mut b: Vec<i32> = a.clone();\n    a.par_chunks_mut(2).for_each(|c| c[0] = c.iter().sum());\n    b.chunks_mut(2).for_each(|c| c[0] = c.iter().sum());\n    assert_eq!(a, &[3, 2, 7, 4, 11, 6, 15, 8, 19, 10]);\n    assert_eq!(a, b);\n\n    let mut a: Vec<i32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n    let mut b: Vec<i32> = a.clone();\n    a.par_chunks_mut(3).for_each(|c| c[0] = c.iter().sum());\n    b.chunks_mut(3).for_each(|c| c[0] = c.iter().sum());\n    assert_eq!(a, &[6, 2, 3, 15, 5, 6, 24, 8, 9, 10]);\n    assert_eq!(a, b);\n}\n\n#[test]\nfn check_windows() {\n    let a: Vec<i32> = (0..1024).collect();\n    let par: Vec<_> = a.par_windows(2).collect();\n    let seq: Vec<_> = a.windows(2).collect();\n    assert_eq!(par, seq);\n\n    let par: Vec<_> = a.par_windows(100).collect();\n    let seq: Vec<_> = a.windows(100).collect();\n    assert_eq!(par, seq);\n\n    let par: Vec<_> = a.par_windows(1_000_000).collect();\n    let seq: Vec<_> = a.windows(1_000_000).collect();\n    assert_eq!(par, seq);\n\n    let par: Vec<_> = a\n        .par_windows(2)\n        .chain(a.par_windows(1_000_000))\n        .zip(a.par_windows(2))\n        .collect();\n    let seq: Vec<_> = a\n        .windows(2)\n        .chain(a.windows(1_000_000))\n        .zip(a.windows(2))\n        .collect();\n    assert_eq!(par, seq);\n}\n\n#[test]\nfn check_options() {\n    let mut a = vec![None, Some(1), None, None, Some(2), Some(4)];\n\n    assert_eq!(7, a.par_iter().flat_map(|opt| opt).sum::<i32>());\n    assert_eq!(7, a.par_iter().flat_map(|opt| opt).sum::<i32>());\n\n    a.par_iter_mut()\n        .flat_map(|opt| opt)\n        .for_each(|x| *x = *x * *x);\n\n    assert_eq!(21, a.into_par_iter().flat_map(|opt| opt).sum::<i32>());\n}\n\n#[test]\nfn check_results() {\n    let mut a = vec![Err(()), Ok(1i32), Err(()), Err(()), Ok(2), Ok(4)];\n\n    assert_eq!(7, a.par_iter().flat_map(|res| res).sum::<i32>());\n\n    assert_eq!(Err::<i32, ()>(()), a.par_iter().cloned().sum());\n    assert_eq!(Ok(7), a.par_iter().cloned().filter(Result::is_ok).sum());\n\n    assert_eq!(Err::<i32, ()>(()), a.par_iter().cloned().product());\n    assert_eq!(Ok(8), a.par_iter().cloned().filter(Result::is_ok).product());\n\n    a.par_iter_mut()\n        .flat_map(|res| res)\n        .for_each(|x| *x = *x * *x);\n\n    assert_eq!(21, a.into_par_iter().flat_map(|res| res).sum::<i32>());\n}\n\n#[test]\nfn check_binary_heap() {\n    use std::collections::BinaryHeap;\n\n    let a: BinaryHeap<i32> = (0..10).collect();\n\n    assert_eq!(45, a.par_iter().sum::<i32>());\n    assert_eq!(45, a.into_par_iter().sum::<i32>());\n}\n\n#[test]\nfn check_btree_map() {\n    use std::collections::BTreeMap;\n\n    let mut a: BTreeMap<i32, i32> = (0..10).map(|i| (i, -i)).collect();\n\n    assert_eq!(45, a.par_iter().map(|(&k, _)| k).sum::<i32>());\n    assert_eq!(-45, a.par_iter().map(|(_, &v)| v).sum::<i32>());\n\n    a.par_iter_mut().for_each(|(k, v)| *v += *k);\n\n    assert_eq!(0, a.into_par_iter().map(|(_, v)| v).sum::<i32>());\n}\n\n#[test]\nfn check_btree_set() {\n    use std::collections::BTreeSet;\n\n    let a: BTreeSet<i32> = (0..10).collect();\n\n    assert_eq!(45, a.par_iter().sum::<i32>());\n    assert_eq!(45, a.into_par_iter().sum::<i32>());\n}\n\n#[test]\nfn check_hash_map() {\n    use std::collections::HashMap;\n\n    let mut a: HashMap<i32, i32> = (0..10).map(|i| (i, -i)).collect();\n\n    assert_eq!(45, a.par_iter().map(|(&k, _)| k).sum::<i32>());\n    assert_eq!(-45, a.par_iter().map(|(_, &v)| v).sum::<i32>());\n\n    a.par_iter_mut().for_each(|(k, v)| *v += *k);\n\n    assert_eq!(0, a.into_par_iter().map(|(_, v)| v).sum::<i32>());\n}\n\n#[test]\nfn check_hash_set() {\n    use std::collections::HashSet;\n\n    let a: HashSet<i32> = (0..10).collect();\n\n    assert_eq!(45, a.par_iter().sum::<i32>());\n    assert_eq!(45, a.into_par_iter().sum::<i32>());\n}\n\n#[test]\nfn check_linked_list() {\n    use std::collections::LinkedList;\n\n    let mut a: LinkedList<i32> = (0..10).collect();\n\n    assert_eq!(45, a.par_iter().sum::<i32>());\n\n    a.par_iter_mut().for_each(|x| *x = -*x);\n\n    assert_eq!(-45, a.into_par_iter().sum::<i32>());\n}\n\n#[test]\nfn check_vec_deque() {\n    use std::collections::VecDeque;\n\n    let mut a: VecDeque<i32> = (0..10).collect();\n\n    // try to get it to wrap around\n    a.drain(..5);\n    a.extend(0..5);\n\n    assert_eq!(45, a.par_iter().sum::<i32>());\n\n    a.par_iter_mut().for_each(|x| *x = -*x);\n\n    assert_eq!(-45, a.into_par_iter().sum::<i32>());\n}\n\n#[test]\nfn check_chain() {\n    let mut res = vec![];\n\n    // stays indexed in the face of madness\n    Some(0)\n        .into_par_iter()\n        .chain(Ok::<_, ()>(1))\n        .chain(1..4)\n        .chain(Err(\"huh?\"))\n        .chain(None)\n        .chain(vec![5, 8, 13])\n        .map(|x| (x as u8 + b'a') as char)\n        .chain(vec!['x', 'y', 'z'])\n        .zip((0i32..1000).into_par_iter().map(|x| -x))\n        .enumerate()\n        .map(|(a, (b, c))| (a, b, c))\n        .chain(None)\n        .collect_into_vec(&mut res);\n\n    assert_eq!(\n        res,\n        vec![\n            (0, 'a', 0),\n            (1, 'b', -1),\n            (2, 'b', -2),\n            (3, 'c', -3),\n            (4, 'd', -4),\n            (5, 'f', -5),\n            (6, 'i', -6),\n            (7, 'n', -7),\n            (8, 'x', -8),\n            (9, 'y', -9),\n            (10, 'z', -10)\n        ]\n    );\n\n    // unindexed is ok too\n    let res: Vec<i32> = Some(1i32)\n        .into_par_iter()\n        .chain(\n            (2i32..4)\n                .into_par_iter()\n                .chain(vec![5, 6, 7, 8, 9])\n                .chain(Some((10, 100)).into_par_iter().flat_map(|(a, b)| a..b))\n                .filter(|x| x & 1 == 1),\n        )\n        .collect();\n    let other: Vec<i32> = (0..100).filter(|x| x & 1 == 1).collect();\n    assert_eq!(res, other);\n\n    // chain collect is ok with the \"fake\" specialization\n    let res: Vec<i32> = Some(1i32).into_par_iter().chain(None).collect();\n    assert_eq!(res, &[1]);\n}\n\n#[test]\nfn check_count() {\n    let c0 = (0_u32..24 * 1024).filter(|i| i % 2 == 0).count();\n    let c1 = (0_u32..24 * 1024)\n        .into_par_iter()\n        .filter(|i| i % 2 == 0)\n        .count();\n    assert_eq!(c0, c1);\n}\n\n#[test]\nfn find_any() {\n    let a: Vec<i32> = (0..1024).collect();\n\n    assert!(a.par_iter().find_any(|&&x| x % 42 == 41).is_some());\n    assert_eq!(\n        a.par_iter().find_any(|&&x| x % 19 == 1 && x % 53 == 0),\n        Some(&742_i32)\n    );\n    assert_eq!(a.par_iter().find_any(|&&x| x < 0), None);\n\n    assert!(a.par_iter().position_any(|&x| x % 42 == 41).is_some());\n    assert_eq!(\n        a.par_iter().position_any(|&x| x % 19 == 1 && x % 53 == 0),\n        Some(742_usize)\n    );\n    assert_eq!(a.par_iter().position_any(|&x| x < 0), None);\n\n    assert!(a.par_iter().any(|&x| x > 1000));\n    assert!(!a.par_iter().any(|&x| x < 0));\n\n    assert!(!a.par_iter().all(|&x| x > 1000));\n    assert!(a.par_iter().all(|&x| x >= 0));\n}\n\n#[test]\nfn find_first_or_last() {\n    let a: Vec<i32> = (0..1024).collect();\n\n    assert_eq!(a.par_iter().find_first(|&&x| x % 42 == 41), Some(&41_i32));\n    assert_eq!(\n        a.par_iter().find_first(|&&x| x % 19 == 1 && x % 53 == 0),\n        Some(&742_i32)\n    );\n    assert_eq!(a.par_iter().find_first(|&&x| x < 0), None);\n\n    assert_eq!(\n        a.par_iter().position_first(|&x| x % 42 == 41),\n        Some(41_usize)\n    );\n    assert_eq!(\n        a.par_iter().position_first(|&x| x % 19 == 1 && x % 53 == 0),\n        Some(742_usize)\n    );\n    assert_eq!(a.par_iter().position_first(|&x| x < 0), None);\n\n    assert_eq!(a.par_iter().find_last(|&&x| x % 42 == 41), Some(&1007_i32));\n    assert_eq!(\n        a.par_iter().find_last(|&&x| x % 19 == 1 && x % 53 == 0),\n        Some(&742_i32)\n    );\n    assert_eq!(a.par_iter().find_last(|&&x| x < 0), None);\n\n    assert_eq!(\n        a.par_iter().position_last(|&x| x % 42 == 41),\n        Some(1007_usize)\n    );\n    assert_eq!(\n        a.par_iter().position_last(|&x| x % 19 == 1 && x % 53 == 0),\n        Some(742_usize)\n    );\n    assert_eq!(a.par_iter().position_last(|&x| x < 0), None);\n}\n\n#[test]\nfn find_map_first_or_last_or_any() {\n    let mut a: Vec<i32> = vec![];\n\n    assert!(a.par_iter().find_map_any(half_if_positive).is_none());\n    assert!(a.par_iter().find_map_first(half_if_positive).is_none());\n    assert!(a.par_iter().find_map_last(half_if_positive).is_none());\n\n    a = (-1024..-3).collect();\n\n    assert!(a.par_iter().find_map_any(half_if_positive).is_none());\n    assert!(a.par_iter().find_map_first(half_if_positive).is_none());\n    assert!(a.par_iter().find_map_last(half_if_positive).is_none());\n\n    assert!(a.par_iter().find_map_any(half_if_negative).is_some());\n    assert_eq!(\n        a.par_iter().find_map_first(half_if_negative),\n        Some(-512_i32)\n    );\n    assert_eq!(a.par_iter().find_map_last(half_if_negative), Some(-2_i32));\n\n    a.append(&mut (2..1025).collect());\n\n    assert!(a.par_iter().find_map_any(half_if_positive).is_some());\n    assert_eq!(a.par_iter().find_map_first(half_if_positive), Some(1_i32));\n    assert_eq!(a.par_iter().find_map_last(half_if_positive), Some(512_i32));\n\n    fn half_if_positive(x: &i32) -> Option<i32> {\n        if *x > 0 {\n            Some(x / 2)\n        } else {\n            None\n        }\n    }\n\n    fn half_if_negative(x: &i32) -> Option<i32> {\n        if *x < 0 {\n            Some(x / 2)\n        } else {\n            None\n        }\n    }\n}\n\n#[test]\nfn check_find_not_present() {\n    let counter = AtomicUsize::new(0);\n    let value: Option<i32> = (0_i32..2048).into_par_iter().find_any(|&p| {\n        counter.fetch_add(1, Ordering::SeqCst);\n        p >= 2048\n    });\n    assert!(value.is_none());\n    assert!(counter.load(Ordering::SeqCst) == 2048); // should have visited every single one\n}\n\n#[test]\nfn check_find_is_present() {\n    let counter = AtomicUsize::new(0);\n    let value: Option<i32> = (0_i32..2048).into_par_iter().find_any(|&p| {\n        counter.fetch_add(1, Ordering::SeqCst);\n        (1024..1096).contains(&p)\n    });\n    let q = value.unwrap();\n    assert!((1024..1096).contains(&q));\n    assert!(counter.load(Ordering::SeqCst) < 2048); // should not have visited every single one\n}\n\n#[test]\nfn check_while_some() {\n    let value = (0_i32..2048).into_par_iter().map(Some).while_some().max();\n    assert_eq!(value, Some(2047));\n\n    let counter = AtomicUsize::new(0);\n    let value = (0_i32..2048)\n        .into_par_iter()\n        .map(|x| {\n            counter.fetch_add(1, Ordering::SeqCst);\n            if x < 1024 {\n                Some(x)\n            } else {\n                None\n            }\n        })\n        .while_some()\n        .max();\n    assert!(value < Some(1024));\n    assert!(counter.load(Ordering::SeqCst) < 2048); // should not have visited every single one\n}\n\n#[test]\nfn par_iter_collect_option() {\n    let a: Option<Vec<_>> = (0_i32..2048).map(Some).collect();\n    let b: Option<Vec<_>> = (0_i32..2048).into_par_iter().map(Some).collect();\n    assert_eq!(a, b);\n\n    let c: Option<Vec<_>> = (0_i32..2048)\n        .into_par_iter()\n        .map(|x| if x == 1234 { None } else { Some(x) })\n        .collect();\n    assert_eq!(c, None);\n}\n\n#[test]\nfn par_iter_collect_result() {\n    let a: Result<Vec<_>, ()> = (0_i32..2048).map(Ok).collect();\n    let b: Result<Vec<_>, ()> = (0_i32..2048).into_par_iter().map(Ok).collect();\n    assert_eq!(a, b);\n\n    let c: Result<Vec<_>, _> = (0_i32..2048)\n        .into_par_iter()\n        .map(|x| if x == 1234 { Err(x) } else { Ok(x) })\n        .collect();\n    assert_eq!(c, Err(1234));\n\n    let d: Result<Vec<_>, _> = (0_i32..2048)\n        .into_par_iter()\n        .map(|x| if x % 100 == 99 { Err(x) } else { Ok(x) })\n        .collect();\n    assert_eq!(d.map_err(|x| x % 100), Err(99));\n}\n\n#[test]\nfn par_iter_collect() {\n    let a: Vec<i32> = (0..1024).collect();\n    let b: Vec<i32> = a.par_iter().map(|&i| i + 1).collect();\n    let c: Vec<i32> = (0..1024).map(|i| i + 1).collect();\n    assert_eq!(b, c);\n}\n\n#[test]\nfn par_iter_collect_vecdeque() {\n    let a: Vec<i32> = (0..1024).collect();\n    let b: VecDeque<i32> = a.par_iter().cloned().collect();\n    let c: VecDeque<i32> = a.iter().cloned().collect();\n    assert_eq!(b, c);\n}\n\n#[test]\nfn par_iter_collect_binaryheap() {\n    let a: Vec<i32> = (0..1024).collect();\n    let mut b: BinaryHeap<i32> = a.par_iter().cloned().collect();\n    assert_eq!(b.peek(), Some(&1023));\n    assert_eq!(b.len(), 1024);\n    for n in (0..1024).rev() {\n        assert_eq!(b.pop(), Some(n));\n        assert_eq!(b.len() as i32, n);\n    }\n}\n\n#[test]\nfn par_iter_collect_hashmap() {\n    let a: Vec<i32> = (0..1024).collect();\n    let b: HashMap<i32, String> = a.par_iter().map(|&i| (i, format!(\"{i}\"))).collect();\n    assert_eq!(&b[&3], \"3\");\n    assert_eq!(b.len(), 1024);\n}\n\n#[test]\nfn par_iter_collect_hashset() {\n    let a: Vec<i32> = (0..1024).collect();\n    let b: HashSet<i32> = a.par_iter().cloned().collect();\n    assert_eq!(b.len(), 1024);\n}\n\n#[test]\nfn par_iter_collect_btreemap() {\n    let a: Vec<i32> = (0..1024).collect();\n    let b: BTreeMap<i32, String> = a.par_iter().map(|&i| (i, format!(\"{i}\"))).collect();\n    assert_eq!(&b[&3], \"3\");\n    assert_eq!(b.len(), 1024);\n}\n\n#[test]\nfn par_iter_collect_btreeset() {\n    let a: Vec<i32> = (0..1024).collect();\n    let b: BTreeSet<i32> = a.par_iter().cloned().collect();\n    assert_eq!(b.len(), 1024);\n}\n\n#[test]\nfn par_iter_collect_linked_list() {\n    let a: Vec<i32> = (0..1024).collect();\n    let b: LinkedList<_> = a.par_iter().map(|&i| (i, format!(\"{i}\"))).collect();\n    let c: LinkedList<_> = a.iter().map(|&i| (i, format!(\"{i}\"))).collect();\n    assert_eq!(b, c);\n}\n\n#[test]\nfn par_iter_collect_linked_list_flat_map_filter() {\n    let b: LinkedList<i32> = (0_i32..1024)\n        .into_par_iter()\n        .flat_map(|i| 0..i)\n        .filter(|&i| i % 2 == 0)\n        .collect();\n    let c: LinkedList<i32> = (0_i32..1024)\n        .flat_map(|i| 0..i)\n        .filter(|&i| i % 2 == 0)\n        .collect();\n    assert_eq!(b, c);\n}\n\n#[test]\nfn par_iter_collect_cows() {\n    use std::borrow::Cow;\n\n    let s = \"Fearless Concurrency with Rust\";\n\n    // Collects `i32` into a `Vec`\n    let a: Cow<'_, [i32]> = (0..1024).collect();\n    let b: Cow<'_, [i32]> = a.par_iter().cloned().collect();\n    assert_eq!(a, b);\n\n    // Collects `char` into a `String`\n    let a: Cow<'_, str> = s.chars().collect();\n    let b: Cow<'_, str> = s.par_chars().collect();\n    assert_eq!(a, b);\n\n    // Collects `str` into a `String`\n    let sw = s.split_whitespace();\n    let psw = s.par_split_whitespace();\n    let a: Cow<'_, str> = sw.clone().collect();\n    let b: Cow<'_, str> = psw.clone().collect();\n    assert_eq!(a, b);\n\n    // Collects `String` into a `String`\n    let a: Cow<'_, str> = sw.map(str::to_owned).collect();\n    let b: Cow<'_, str> = psw.map(str::to_owned).collect();\n    assert_eq!(a, b);\n\n    // Collects `OsStr` into a `OsString`\n    let sw = s.split_whitespace().map(OsStr::new);\n    let psw = s.par_split_whitespace().map(OsStr::new);\n    let a: Cow<'_, OsStr> = Cow::Owned(sw.clone().collect());\n    let b: Cow<'_, OsStr> = psw.clone().collect();\n    assert_eq!(a, b);\n\n    // Collects `OsString` into a `OsString`\n    let a: Cow<'_, OsStr> = Cow::Owned(sw.map(OsStr::to_owned).collect());\n    let b: Cow<'_, OsStr> = psw.map(OsStr::to_owned).collect();\n    assert_eq!(a, b);\n}\n\n#[test]\nfn par_iter_unindexed_flat_map() {\n    let b: Vec<i64> = (0_i64..1024).into_par_iter().flat_map(Some).collect();\n    let c: Vec<i64> = (0_i64..1024).flat_map(Some).collect();\n    assert_eq!(b, c);\n}\n\n#[test]\nfn min_max() {\n    let rng = seeded_rng();\n    let a: Vec<i32> = rng.sample_iter(&StandardUniform).take(1024).collect();\n    for i in 0..=a.len() {\n        let slice = &a[..i];\n        assert_eq!(slice.par_iter().min(), slice.iter().min());\n        assert_eq!(slice.par_iter().max(), slice.iter().max());\n    }\n}\n\n#[test]\nfn min_max_by() {\n    let rng = seeded_rng();\n    // Make sure there are duplicate keys, for testing sort stability\n    let r: Vec<i32> = rng.sample_iter(&StandardUniform).take(512).collect();\n    let a: Vec<(i32, u16)> = r.iter().chain(&r).cloned().zip(0..).collect();\n    for i in 0..=a.len() {\n        let slice = &a[..i];\n        assert_eq!(\n            slice.par_iter().min_by(|x, y| x.0.cmp(&y.0)),\n            slice.iter().min_by(|x, y| x.0.cmp(&y.0))\n        );\n        assert_eq!(\n            slice.par_iter().max_by(|x, y| x.0.cmp(&y.0)),\n            slice.iter().max_by(|x, y| x.0.cmp(&y.0))\n        );\n    }\n}\n\n#[test]\nfn min_max_by_key() {\n    let rng = seeded_rng();\n    // Make sure there are duplicate keys, for testing sort stability\n    let r: Vec<i32> = rng.sample_iter(&StandardUniform).take(512).collect();\n    let a: Vec<(i32, u16)> = r.iter().chain(&r).cloned().zip(0..).collect();\n    for i in 0..=a.len() {\n        let slice = &a[..i];\n        assert_eq!(\n            slice.par_iter().min_by_key(|x| x.0),\n            slice.iter().min_by_key(|x| x.0)\n        );\n        assert_eq!(\n            slice.par_iter().max_by_key(|x| x.0),\n            slice.iter().max_by_key(|x| x.0)\n        );\n    }\n}\n\n#[test]\nfn check_rev() {\n    let a: Vec<usize> = (0..1024).rev().collect();\n    let b: Vec<usize> = (0..1024).collect();\n\n    assert!(a.par_iter().rev().zip(b).all(|(&a, b)| a == b));\n}\n\n#[test]\nfn scope_mix() {\n    let counter_p = &AtomicUsize::new(0);\n    scope(|s| {\n        s.spawn(move |s| {\n            divide_and_conquer(s, counter_p, 1024);\n        });\n        s.spawn(move |_| {\n            let a: Vec<i32> = (0..1024).collect();\n            let r1 = a.par_iter().map(|&i| i + 1).reduce_with(|i, j| i + j);\n            let r2 = a.iter().map(|&i| i + 1).sum();\n            assert_eq!(r1.unwrap(), r2);\n        });\n    });\n}\n\nfn divide_and_conquer<'scope>(scope: &Scope<'scope>, counter: &'scope AtomicUsize, size: usize) {\n    if size > 1 {\n        scope.spawn(move |scope| divide_and_conquer(scope, counter, size / 2));\n        scope.spawn(move |scope| divide_and_conquer(scope, counter, size / 2));\n    } else {\n        // count the leaves\n        counter.fetch_add(1, Ordering::SeqCst);\n    }\n}\n\n#[test]\nfn check_split() {\n    use std::ops::Range;\n\n    let a = (0..1024).into_par_iter();\n\n    let b = split(0..1024, |Range { start, end }| {\n        let mid = (end - start) / 2;\n        if mid > start {\n            (start..mid, Some(mid..end))\n        } else {\n            (start..end, None)\n        }\n    })\n    .flat_map(|range| range);\n\n    assert_eq!(a.collect::<Vec<_>>(), b.collect::<Vec<_>>());\n}\n\n#[test]\nfn check_lengths() {\n    fn check(min: usize, max: usize) {\n        let range = 0..1024 * 1024;\n\n        // Check against normalized values.\n        let min_check = Ord::min(Ord::max(min, 1), range.len());\n        let max_check = Ord::max(max, min_check.saturating_add(min_check - 1));\n\n        assert!(\n            range\n                .into_par_iter()\n                .with_min_len(min)\n                .with_max_len(max)\n                .fold(|| 0, |count, _| count + 1)\n                .all(|c| c >= min_check && c <= max_check),\n            \"check_lengths failed {:?} -> {:?} \",\n            (min, max),\n            (min_check, max_check)\n        );\n    }\n\n    let lengths = [0, 1, 10, 100, 1_000, 10_000, 100_000, 1_000_000, usize::MAX];\n    for &min in &lengths {\n        for &max in &lengths {\n            check(min, max);\n        }\n    }\n}\n\n#[test]\nfn check_map_with() {\n    let (sender, receiver) = mpsc::channel();\n    let a: HashSet<_> = (0..1024).collect();\n\n    a.par_iter()\n        .cloned()\n        .map_with(sender, |s, i| s.send(i).unwrap())\n        .count();\n\n    let b: HashSet<_> = receiver.iter().collect();\n    assert_eq!(a, b);\n}\n\n#[test]\nfn check_fold_with() {\n    let (sender, receiver) = mpsc::channel();\n    let a: HashSet<_> = (0..1024).collect();\n\n    a.par_iter()\n        .cloned()\n        .fold_with(sender, |s, i| {\n            s.send(i).unwrap();\n            s\n        })\n        .count();\n\n    let b: HashSet<_> = receiver.iter().collect();\n    assert_eq!(a, b);\n}\n\n#[test]\nfn check_for_each_with() {\n    let (sender, receiver) = mpsc::channel();\n    let a: HashSet<_> = (0..1024).collect();\n\n    a.par_iter()\n        .cloned()\n        .for_each_with(sender, |s, i| s.send(i).unwrap());\n\n    let b: HashSet<_> = receiver.iter().collect();\n    assert_eq!(a, b);\n}\n\n#[test]\nfn check_extend_items() {\n    fn check<C>()\n    where\n        C: Default\n            + Eq\n            + Debug\n            + Extend<i32>\n            + for<'a> Extend<&'a i32>\n            + ParallelExtend<i32>\n            + for<'a> ParallelExtend<&'a i32>,\n    {\n        let mut serial = C::default();\n        let mut parallel = C::default();\n\n        // extend with references\n        let v: Vec<_> = (0..128).collect();\n        serial.extend(&v);\n        parallel.par_extend(&v);\n        assert_eq!(serial, parallel);\n\n        // extend with values\n        serial.extend(-128..0);\n        parallel.par_extend(-128..0);\n        assert_eq!(serial, parallel);\n    }\n\n    check::<BTreeSet<_>>();\n    check::<HashSet<_>>();\n    check::<LinkedList<_>>();\n    check::<Vec<_>>();\n    check::<VecDeque<_>>();\n}\n\n#[test]\nfn check_extend_heap() {\n    let mut serial: BinaryHeap<_> = Default::default();\n    let mut parallel: BinaryHeap<_> = Default::default();\n\n    // extend with references\n    let v: Vec<_> = (0..128).collect();\n    serial.extend(&v);\n    parallel.par_extend(&v);\n    assert_eq!(\n        serial.clone().into_sorted_vec(),\n        parallel.clone().into_sorted_vec()\n    );\n\n    // extend with values\n    serial.extend(-128..0);\n    parallel.par_extend(-128..0);\n    assert_eq!(serial.into_sorted_vec(), parallel.into_sorted_vec());\n}\n\n#[test]\nfn check_extend_pairs() {\n    fn check<C>()\n    where\n        C: Default\n            + Eq\n            + Debug\n            + Extend<(usize, i32)>\n            + for<'a> Extend<(&'a usize, &'a i32)>\n            + ParallelExtend<(usize, i32)>\n            + for<'a> ParallelExtend<(&'a usize, &'a i32)>,\n    {\n        let mut serial = C::default();\n        let mut parallel = C::default();\n\n        // extend with references\n        let m: HashMap<_, _> = (0..128).enumerate().collect();\n        serial.extend(&m);\n        parallel.par_extend(&m);\n        assert_eq!(serial, parallel);\n\n        // extend with values\n        let v: Vec<(_, _)> = (-128..0).enumerate().collect();\n        serial.extend(v.clone());\n        parallel.par_extend(v);\n        assert_eq!(serial, parallel);\n    }\n\n    check::<BTreeMap<usize, i32>>();\n    check::<HashMap<usize, i32>>();\n}\n\n#[test]\nfn check_unzip_into_vecs() {\n    let mut a = vec![];\n    let mut b = vec![];\n    (0..1024)\n        .into_par_iter()\n        .map(|i| i * i)\n        .enumerate()\n        .unzip_into_vecs(&mut a, &mut b);\n\n    let (c, d): (Vec<_>, Vec<_>) = (0..1024).map(|i| i * i).enumerate().unzip();\n    assert_eq!(a, c);\n    assert_eq!(b, d);\n}\n\n#[test]\nfn check_unzip() {\n    // indexed, unindexed\n    let (a, b): (Vec<_>, HashSet<_>) = (0..1024).into_par_iter().map(|i| i * i).enumerate().unzip();\n    let (c, d): (Vec<_>, HashSet<_>) = (0..1024).map(|i| i * i).enumerate().unzip();\n    assert_eq!(a, c);\n    assert_eq!(b, d);\n\n    // unindexed, indexed\n    let (a, b): (HashSet<_>, Vec<_>) = (0..1024).into_par_iter().map(|i| i * i).enumerate().unzip();\n    let (c, d): (HashSet<_>, Vec<_>) = (0..1024).map(|i| i * i).enumerate().unzip();\n    assert_eq!(a, c);\n    assert_eq!(b, d);\n\n    // indexed, indexed\n    let (a, b): (Vec<_>, Vec<_>) = (0..1024).into_par_iter().map(|i| i * i).enumerate().unzip();\n    let (c, d): (Vec<_>, Vec<_>) = (0..1024).map(|i| i * i).enumerate().unzip();\n    assert_eq!(a, c);\n    assert_eq!(b, d);\n\n    // unindexed producer\n    let (a, b): (Vec<_>, Vec<_>) = (0..1024)\n        .into_par_iter()\n        .filter_map(|i| Some((i, i * i)))\n        .unzip();\n    let (c, d): (Vec<_>, Vec<_>) = (0..1024).map(|i| (i, i * i)).unzip();\n    assert_eq!(a, c);\n    assert_eq!(b, d);\n}\n\n#[test]\nfn check_partition() {\n    let (a, b): (Vec<_>, Vec<_>) = (0..1024).into_par_iter().partition(|&i| i % 3 == 0);\n    let (c, d): (Vec<_>, Vec<_>) = (0..1024).partition(|&i| i % 3 == 0);\n    assert_eq!(a, c);\n    assert_eq!(b, d);\n}\n\n#[test]\nfn check_partition_map() {\n    let input = \"a b c 1 2 3 x y z\";\n    let (a, b): (Vec<_>, String) =\n        input\n            .par_split_whitespace()\n            .partition_map(|s| match s.parse::<i32>() {\n                Ok(n) => Either::Left(n),\n                Err(_) => Either::Right(s),\n            });\n    assert_eq!(a, vec![1, 2, 3]);\n    assert_eq!(b, \"abcxyz\");\n}\n\n#[test]\nfn check_either() {\n    type I = crate::vec::IntoIter<i32>;\n    type E = Either<I, I>;\n\n    let v: Vec<i32> = (0..1024).collect();\n\n    // try iterating the left side\n    let left: E = Either::Left(v.clone().into_par_iter());\n    assert!(left.eq(v.clone()));\n\n    // try iterating the right side\n    let right: E = Either::Right(v.clone().into_par_iter());\n    assert!(right.eq(v.clone()));\n\n    // try an indexed iterator\n    let left: E = Either::Left(v.clone().into_par_iter());\n    assert!(left.enumerate().eq(v.into_par_iter().enumerate()));\n}\n\n#[test]\nfn check_either_extend() {\n    type E = Either<Vec<i32>, HashSet<i32>>;\n\n    let v: Vec<i32> = (0..1024).collect();\n\n    // try extending the left side\n    let mut left: E = Either::Left(vec![]);\n    left.par_extend(v.clone());\n    assert_eq!(left.as_ref(), Either::Left(&v));\n\n    // try extending the right side\n    let mut right: E = Either::Right(HashSet::default());\n    right.par_extend(v.clone());\n    assert_eq!(right, Either::Right(v.iter().cloned().collect()));\n}\n\n#[test]\nfn check_interleave_eq() {\n    let xs: Vec<usize> = (0..10).collect();\n    let ys: Vec<usize> = (10..20).collect();\n\n    let mut actual = vec![];\n    xs.par_iter()\n        .interleave(&ys)\n        .map(|&i| i)\n        .collect_into_vec(&mut actual);\n\n    let expected: Vec<usize> = (0..10)\n        .zip(10..20)\n        .flat_map(|(i, j)| vec![i, j].into_iter())\n        .collect();\n    assert_eq!(expected, actual);\n}\n\n#[test]\nfn check_interleave_uneven() {\n    let cases: Vec<(Vec<usize>, Vec<usize>, Vec<usize>)> = vec![\n        (\n            (0..9).collect(),\n            vec![10],\n            vec![0, 10, 1, 2, 3, 4, 5, 6, 7, 8],\n        ),\n        (\n            vec![10],\n            (0..9).collect(),\n            vec![10, 0, 1, 2, 3, 4, 5, 6, 7, 8],\n        ),\n        (\n            (0..5).collect(),\n            (5..10).collect(),\n            (0..5)\n                .zip(5..10)\n                .flat_map(|(i, j)| vec![i, j].into_iter())\n                .collect(),\n        ),\n        (vec![], (0..9).collect(), (0..9).collect()),\n        ((0..9).collect(), vec![], (0..9).collect()),\n        (\n            (0..50).collect(),\n            (50..100).collect(),\n            (0..50)\n                .zip(50..100)\n                .flat_map(|(i, j)| vec![i, j].into_iter())\n                .collect(),\n        ),\n    ];\n\n    for (i, (xs, ys, expected)) in cases.into_iter().enumerate() {\n        let mut res = vec![];\n        xs.par_iter()\n            .interleave(&ys)\n            .map(|&i| i)\n            .collect_into_vec(&mut res);\n        assert_eq!(expected, res, \"Case {i} failed\");\n\n        res.truncate(0);\n        xs.par_iter()\n            .interleave(&ys)\n            .rev()\n            .map(|&i| i)\n            .collect_into_vec(&mut res);\n        assert_eq!(\n            expected.into_iter().rev().collect::<Vec<usize>>(),\n            res,\n            \"Case {i} reversed failed\"\n        );\n    }\n}\n\n#[test]\nfn check_interleave_shortest() {\n    let cases: Vec<(Vec<usize>, Vec<usize>, Vec<usize>)> = vec![\n        ((0..9).collect(), vec![10], vec![0, 10, 1]),\n        (vec![10], (0..9).collect(), vec![10, 0]),\n        (\n            (0..5).collect(),\n            (5..10).collect(),\n            (0..5)\n                .zip(5..10)\n                .flat_map(|(i, j)| vec![i, j].into_iter())\n                .collect(),\n        ),\n        (vec![], (0..9).collect(), vec![]),\n        ((0..9).collect(), vec![], vec![0]),\n        (\n            (0..50).collect(),\n            (50..100).collect(),\n            (0..50)\n                .zip(50..100)\n                .flat_map(|(i, j)| vec![i, j].into_iter())\n                .collect(),\n        ),\n    ];\n\n    for (i, (xs, ys, expected)) in cases.into_iter().enumerate() {\n        let mut res = vec![];\n        xs.par_iter()\n            .interleave_shortest(&ys)\n            .map(|&i| i)\n            .collect_into_vec(&mut res);\n        assert_eq!(expected, res, \"Case {i} failed\");\n\n        res.truncate(0);\n        xs.par_iter()\n            .interleave_shortest(&ys)\n            .rev()\n            .map(|&i| i)\n            .collect_into_vec(&mut res);\n        assert_eq!(\n            expected.into_iter().rev().collect::<Vec<usize>>(),\n            res,\n            \"Case {i} reversed failed\"\n        );\n    }\n}\n\n#[test]\n#[should_panic(expected = \"chunk_size must not be zero\")]\nfn check_chunks_zero_size() {\n    let _: Vec<Vec<i32>> = vec![1, 2, 3].into_par_iter().chunks(0).collect();\n}\n\n#[test]\nfn check_chunks_even_size() {\n    assert_eq!(\n        vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]],\n        (1..10).into_par_iter().chunks(3).collect::<Vec<Vec<i32>>>()\n    );\n}\n\n#[test]\nfn check_chunks_empty() {\n    let v: Vec<i32> = vec![];\n    let expected: Vec<Vec<i32>> = vec![];\n    assert_eq!(\n        expected,\n        v.into_par_iter().chunks(2).collect::<Vec<Vec<i32>>>()\n    );\n}\n\n#[test]\nfn check_chunks_len() {\n    assert_eq!(4, (0..8).into_par_iter().chunks(2).len());\n    assert_eq!(3, (0..9).into_par_iter().chunks(3).len());\n    assert_eq!(3, (0..8).into_par_iter().chunks(3).len());\n    assert_eq!(1, [1].par_iter().chunks(3).len());\n    assert_eq!(0, (0..0).into_par_iter().chunks(3).len());\n}\n\n#[test]\nfn check_chunks_uneven() {\n    let cases: Vec<(Vec<u32>, usize, Vec<Vec<u32>>)> = vec![\n        ((0..5).collect(), 3, vec![vec![0, 1, 2], vec![3, 4]]),\n        (vec![1], 5, vec![vec![1]]),\n        ((0..4).collect(), 3, vec![vec![0, 1, 2], vec![3]]),\n    ];\n\n    for (i, (v, n, expected)) in cases.into_iter().enumerate() {\n        let mut res: Vec<Vec<u32>> = vec![];\n        v.par_iter()\n            .chunks(n)\n            .map(|v| v.into_iter().cloned().collect())\n            .collect_into_vec(&mut res);\n        assert_eq!(expected, res, \"Case {i} failed\");\n\n        res.truncate(0);\n        v.into_par_iter().chunks(n).rev().collect_into_vec(&mut res);\n        assert_eq!(\n            expected.into_iter().rev().collect::<Vec<Vec<u32>>>(),\n            res,\n            \"Case {i} reversed failed\"\n        );\n    }\n}\n\n#[test]\n#[ignore] // it's quick enough on optimized 32-bit platforms, but otherwise... ... ...\n#[should_panic(expected = \"overflow\")]\n#[cfg(debug_assertions)]\nfn check_repeat_unbounded() {\n    // use just one thread, so we don't get infinite adaptive splitting\n    // (forever stealing and re-splitting jobs that will panic on overflow)\n    let pool = ThreadPoolBuilder::new().num_threads(1).build().unwrap();\n    pool.install(|| {\n        println!(\"counted {} repeats\", repeat(()).count());\n    });\n}\n\n#[test]\nfn check_repeat_find_any() {\n    let even = repeat(4).find_any(|&x| x % 2 == 0);\n    assert_eq!(even, Some(4));\n}\n\n#[test]\nfn check_repeat_take() {\n    let v: Vec<_> = repeat(4).take(4).collect();\n    assert_eq!(v, [4, 4, 4, 4]);\n}\n\n#[test]\nfn check_repeat_zip() {\n    let v = vec![4, 4, 4, 4];\n    let mut fours: Vec<_> = repeat(4).zip(v).collect();\n    assert_eq!(fours.len(), 4);\n    while let Some(item) = fours.pop() {\n        assert_eq!(item, (4, 4));\n    }\n}\n\n#[test]\nfn check_repeat_n_zip_left() {\n    let v = vec![4, 4, 4, 4];\n    let mut fours: Vec<_> = repeat_n(4, usize::MAX).zip(v).collect();\n    assert_eq!(fours.len(), 4);\n    while let Some(item) = fours.pop() {\n        assert_eq!(item, (4, 4));\n    }\n}\n\n#[test]\nfn check_repeat_n_zip_right() {\n    let v = vec![4, 4, 4, 4];\n    let mut fours: Vec<_> = v.into_par_iter().zip(repeat_n(4, usize::MAX)).collect();\n    assert_eq!(fours.len(), 4);\n    while let Some(item) = fours.pop() {\n        assert_eq!(item, (4, 4));\n    }\n}\n\n#[test]\nfn count_repeat_n_clones() {\n    use std::sync::atomic::{AtomicUsize, Ordering};\n\n    static CLONES: AtomicUsize = AtomicUsize::new(0);\n    static DROPS: AtomicUsize = AtomicUsize::new(0);\n\n    struct Counter;\n\n    impl Clone for Counter {\n        fn clone(&self) -> Self {\n            CLONES.fetch_add(1, Ordering::Relaxed);\n            Counter\n        }\n    }\n\n    impl Drop for Counter {\n        fn drop(&mut self) {\n            DROPS.fetch_add(1, Ordering::Relaxed);\n        }\n    }\n\n    #[track_caller]\n    fn check(clones: usize, drops: usize) {\n        assert_eq!(CLONES.swap(0, Ordering::Relaxed), clones, \"clones\");\n        assert_eq!(DROPS.swap(0, Ordering::Relaxed), drops, \"drops\");\n    }\n\n    drop(repeat_n(Counter, 100));\n    check(0, 1);\n\n    let empty = repeat_n(Counter, 0);\n    check(0, 1);\n    let empty2 = empty.clone();\n    check(0, 0);\n    assert_eq!(empty.count(), 0);\n    assert_eq!(empty2.count(), 0);\n    check(0, 0);\n\n    let par_iter = repeat_n(Counter, 100);\n    let par_iter2 = par_iter.clone();\n    check(1, 0);\n    assert_eq!(par_iter.count(), 100);\n    check(99, 100);\n    assert_eq!(par_iter2.map(std::mem::forget).count(), 100);\n    check(99, 0);\n\n    // Clone once in `split_at` and again for the first item, leaving its unused tail.\n    // The other split doesn't have a tail, so it can avoid a clone.\n    let step99 = repeat_n(Counter, 100).step_by(99);\n    assert_eq!(step99.count(), 2);\n    check(2, 3);\n\n    // Same without any parallel splitting\n    let step99 = repeat_n(Counter, 100).step_by(99).with_min_len(2);\n    assert_eq!(step99.count(), 2);\n    check(1, 2);\n\n    // Clone once in `split_at` and again for both items, leaving both unused tails.\n    let step50 = repeat_n(Counter, 100).step_by(50);\n    assert_eq!(step50.count(), 2);\n    check(3, 4);\n}\n\n#[test]\nfn check_empty() {\n    // drive_unindexed\n    let mut v: Vec<i32> = empty().filter(|_| unreachable!()).collect();\n    assert!(v.is_empty());\n\n    // drive (indexed)\n    empty().collect_into_vec(&mut v);\n    assert!(v.is_empty());\n\n    // with_producer\n    let v: Vec<(i32, i32)> = empty().zip(1..10).collect();\n    assert!(v.is_empty());\n}\n\n#[test]\nfn check_once() {\n    // drive_unindexed\n    let mut v: Vec<i32> = once(42).filter(|_| true).collect();\n    assert_eq!(v, &[42]);\n\n    // drive (indexed)\n    once(42).collect_into_vec(&mut v);\n    assert_eq!(v, &[42]);\n\n    // with_producer\n    let v: Vec<(i32, i32)> = once(42).zip(1..10).collect();\n    assert_eq!(v, &[(42, 1)]);\n}\n\n#[test]\nfn check_update() {\n    let mut v: Vec<Vec<_>> = vec![vec![1], vec![3, 2, 1]];\n    v.par_iter_mut().update(|v| v.push(0)).for_each(|_| ());\n\n    assert_eq!(v, vec![vec![1, 0], vec![3, 2, 1, 0]]);\n}\n\n#[test]\nfn walk_tree_prefix() {\n    let v: Vec<u32> = crate::iter::walk_tree_prefix(0u32..100, |r| {\n        // root is smallest\n        let mid = (r.start + 1 + r.end) / 2;\n        // small indices to the left, large to the right\n        std::iter::once((r.start + 1)..mid)\n            .chain(std::iter::once(mid..r.end))\n            .filter(|r| !r.is_empty())\n    })\n    .map(|r| r.start)\n    .collect();\n    assert!(v.into_iter().eq(0..100));\n}\n\n#[test]\nfn walk_tree_postfix() {\n    let v: Vec<_> = crate::iter::walk_tree_postfix(0u64..100, |r| {\n        // root is largest\n        let mid = (r.start + r.end - 1) / 2;\n        // small indices to the left, large to the right\n        std::iter::once(r.start..mid)\n            .chain(std::iter::once(mid..(r.end - 1)))\n            .filter(|r| !r.is_empty())\n    })\n    .map(|r| r.end - 1)\n    .collect();\n    assert!(v.into_iter().eq(0..100));\n}\n\n#[test]\nfn walk_flat_tree_prefix() {\n    let v: Vec<_> =\n        crate::iter::walk_tree_prefix(0, |&e| if e < 99 { Some(e + 1) } else { None }).collect();\n    assert!(v.into_iter().eq(0..100));\n}\n\n#[test]\nfn walk_flat_tree_postfix() {\n    let v: Vec<_> =\n        crate::iter::walk_tree_postfix(99, |&e| if e > 0 { Some(e - 1) } else { None }).collect();\n    assert!(v.into_iter().eq(0..100));\n}\n\n#[test]\nfn walk_tree_prefix_degree5() {\n    let depth = 5;\n    let nodes_number = (1 - 5i32.pow(depth)) / (1 - 5);\n    let nodes = (0..nodes_number).collect::<Vec<_>>();\n    let v: Vec<i32> = crate::iter::walk_tree_prefix(nodes.as_slice(), |&r| {\n        r.split_first()\n            .into_iter()\n            .filter_map(|(_, r)| if r.is_empty() { None } else { Some(r) })\n            .flat_map(|r| r.chunks(r.len() / 5))\n    })\n    .filter_map(|r| r.first().copied())\n    .collect();\n    assert_eq!(v, nodes);\n}\n\n#[test]\nfn walk_tree_postfix_degree5() {\n    let depth = 5;\n    let nodes_number = (1 - 5i32.pow(depth)) / (1 - 5);\n    let nodes = (0..nodes_number).collect::<Vec<_>>();\n    let v: Vec<i32> = crate::iter::walk_tree_postfix(nodes.as_slice(), |&r| {\n        r.split_last()\n            .into_iter()\n            .filter_map(|(_, r)| if r.is_empty() { None } else { Some(r) })\n            .flat_map(|r| r.chunks(r.len() / 5))\n    })\n    .filter_map(|r| r.last().copied())\n    .collect();\n    assert_eq!(v, nodes)\n}\n\n#[test]\nfn blocks() {\n    let count = AtomicUsize::new(0);\n    let v: Vec<usize> = (0..1000)\n        .into_par_iter()\n        .map(|_| count.fetch_add(1, Ordering::Relaxed))\n        .by_uniform_blocks(100)\n        .collect();\n    let m = v\n        .chunks(100)\n        .map(|c| c.iter().max().copied().unwrap())\n        .collect::<Vec<usize>>();\n    assert!(m.windows(2).all(|w| w[0].lt(&w[1])));\n    assert_eq!(v.len(), 1000);\n}\n"
  },
  {
    "path": "src/iter/try_fold.rs",
    "content": "use super::plumbing::*;\nuse super::ParallelIterator;\nuse super::Try;\n\nuse std::fmt::{self, Debug};\nuse std::marker::PhantomData;\nuse std::ops::ControlFlow::{self, Break, Continue};\n\nimpl<I, U, ID, F> TryFold<I, U, ID, F> {\n    pub(super) fn new(base: I, identity: ID, fold_op: F) -> Self {\n        TryFold {\n            base,\n            identity,\n            fold_op,\n            marker: PhantomData,\n        }\n    }\n}\n\n/// `TryFold` is an iterator that applies a function over an iterator producing a single value.\n/// This struct is created by the [`try_fold()`] method on [`ParallelIterator`]\n///\n/// [`try_fold()`]: ParallelIterator::try_fold()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Clone)]\npub struct TryFold<I, U, ID, F> {\n    base: I,\n    identity: ID,\n    fold_op: F,\n    marker: PhantomData<U>,\n}\n\nimpl<U, I: ParallelIterator + Debug, ID, F> Debug for TryFold<I, U, ID, F> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"TryFold\").field(\"base\", &self.base).finish()\n    }\n}\n\nimpl<U, I, ID, F> ParallelIterator for TryFold<I, U, ID, F>\nwhere\n    I: ParallelIterator,\n    F: Fn(U::Output, I::Item) -> U + Sync + Send,\n    ID: Fn() -> U::Output + Sync + Send,\n    U: Try + Send,\n{\n    type Item = U;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer1 = TryFoldConsumer {\n            base: consumer,\n            identity: &self.identity,\n            fold_op: &self.fold_op,\n            marker: PhantomData,\n        };\n        self.base.drive_unindexed(consumer1)\n    }\n}\n\nstruct TryFoldConsumer<'c, U, C, ID, F> {\n    base: C,\n    identity: &'c ID,\n    fold_op: &'c F,\n    marker: PhantomData<U>,\n}\n\nimpl<'r, U, T, C, ID, F> Consumer<T> for TryFoldConsumer<'r, U, C, ID, F>\nwhere\n    C: Consumer<U>,\n    F: Fn(U::Output, T) -> U + Sync,\n    ID: Fn() -> U::Output + Sync,\n    U: Try + Send,\n{\n    type Folder = TryFoldFolder<'r, C::Folder, U, F>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            TryFoldConsumer { base: left, ..self },\n            TryFoldConsumer {\n                base: right,\n                ..self\n            },\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        TryFoldFolder {\n            base: self.base.into_folder(),\n            control: Continue((self.identity)()),\n            fold_op: self.fold_op,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\nimpl<'r, U, T, C, ID, F> UnindexedConsumer<T> for TryFoldConsumer<'r, U, C, ID, F>\nwhere\n    C: UnindexedConsumer<U>,\n    F: Fn(U::Output, T) -> U + Sync,\n    ID: Fn() -> U::Output + Sync,\n    U: Try + Send,\n{\n    fn split_off_left(&self) -> Self {\n        TryFoldConsumer {\n            base: self.base.split_off_left(),\n            ..*self\n        }\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n\nstruct TryFoldFolder<'r, C, U: Try, F> {\n    base: C,\n    fold_op: &'r F,\n    control: ControlFlow<U::Residual, U::Output>,\n}\n\nimpl<'r, C, U, F, T> Folder<T> for TryFoldFolder<'r, C, U, F>\nwhere\n    C: Folder<U>,\n    F: Fn(U::Output, T) -> U + Sync,\n    U: Try,\n{\n    type Result = C::Result;\n\n    fn consume(mut self, item: T) -> Self {\n        let fold_op = self.fold_op;\n        if let Continue(acc) = self.control {\n            self.control = fold_op(acc, item).branch();\n        }\n        self\n    }\n\n    fn complete(self) -> C::Result {\n        let item = match self.control {\n            Continue(c) => U::from_output(c),\n            Break(r) => U::from_residual(r),\n        };\n        self.base.consume(item).complete()\n    }\n\n    fn full(&self) -> bool {\n        match self.control {\n            Break(_) => true,\n            _ => self.base.full(),\n        }\n    }\n}\n\n// ///////////////////////////////////////////////////////////////////////////\n\nimpl<I, U: Try, F> TryFoldWith<I, U, F> {\n    pub(super) fn new(base: I, item: U::Output, fold_op: F) -> Self {\n        TryFoldWith {\n            base,\n            item,\n            fold_op,\n        }\n    }\n}\n\n/// `TryFoldWith` is an iterator that applies a function over an iterator producing a single value.\n/// This struct is created by the [`try_fold_with()`] method on [`ParallelIterator`]\n///\n/// [`try_fold_with()`]: ParallelIterator::try_fold_with()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Clone)]\npub struct TryFoldWith<I, U: Try, F> {\n    base: I,\n    item: U::Output,\n    fold_op: F,\n}\n\nimpl<I, U, F> Debug for TryFoldWith<I, U, F>\nwhere\n    I: Debug,\n    U: Try<Output: Debug>,\n{\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"TryFoldWith\")\n            .field(\"base\", &self.base)\n            .field(\"item\", &self.item)\n            .finish()\n    }\n}\n\nimpl<U, I, F> ParallelIterator for TryFoldWith<I, U, F>\nwhere\n    I: ParallelIterator,\n    F: Fn(U::Output, I::Item) -> U + Sync + Send,\n    U: Try<Output: Clone + Send> + Send,\n{\n    type Item = U;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer1 = TryFoldWithConsumer {\n            base: consumer,\n            item: self.item,\n            fold_op: &self.fold_op,\n        };\n        self.base.drive_unindexed(consumer1)\n    }\n}\n\nstruct TryFoldWithConsumer<'c, C, U: Try, F> {\n    base: C,\n    item: U::Output,\n    fold_op: &'c F,\n}\n\nimpl<'r, U, T, C, F> Consumer<T> for TryFoldWithConsumer<'r, C, U, F>\nwhere\n    C: Consumer<U>,\n    F: Fn(U::Output, T) -> U + Sync,\n    U: Try<Output: Clone + Send> + Send,\n{\n    type Folder = TryFoldFolder<'r, C::Folder, U, F>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            TryFoldWithConsumer {\n                base: left,\n                item: self.item.clone(),\n                ..self\n            },\n            TryFoldWithConsumer {\n                base: right,\n                ..self\n            },\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        TryFoldFolder {\n            base: self.base.into_folder(),\n            control: Continue(self.item),\n            fold_op: self.fold_op,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\nimpl<'r, U, T, C, F> UnindexedConsumer<T> for TryFoldWithConsumer<'r, C, U, F>\nwhere\n    C: UnindexedConsumer<U>,\n    F: Fn(U::Output, T) -> U + Sync,\n    U: Try<Output: Clone + Send> + Send,\n{\n    fn split_off_left(&self) -> Self {\n        TryFoldWithConsumer {\n            base: self.base.split_off_left(),\n            item: self.item.clone(),\n            ..*self\n        }\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n"
  },
  {
    "path": "src/iter/try_reduce.rs",
    "content": "use super::plumbing::*;\nuse super::ParallelIterator;\nuse super::Try;\n\nuse std::ops::ControlFlow::{self, Break, Continue};\nuse std::sync::atomic::{AtomicBool, Ordering};\n\npub(super) fn try_reduce<PI, R, ID, T>(pi: PI, identity: ID, reduce_op: R) -> T\nwhere\n    PI: ParallelIterator<Item = T>,\n    R: Fn(T::Output, T::Output) -> T + Sync,\n    ID: Fn() -> T::Output + Sync,\n    T: Try + Send,\n{\n    let full = AtomicBool::new(false);\n    let consumer = TryReduceConsumer {\n        identity: &identity,\n        reduce_op: &reduce_op,\n        full: &full,\n    };\n    pi.drive_unindexed(consumer)\n}\n\nstruct TryReduceConsumer<'r, R, ID> {\n    identity: &'r ID,\n    reduce_op: &'r R,\n    full: &'r AtomicBool,\n}\n\nimpl<'r, R, ID> Copy for TryReduceConsumer<'r, R, ID> {}\n\nimpl<'r, R, ID> Clone for TryReduceConsumer<'r, R, ID> {\n    fn clone(&self) -> Self {\n        *self\n    }\n}\n\nimpl<'r, R, ID, T> Consumer<T> for TryReduceConsumer<'r, R, ID>\nwhere\n    R: Fn(T::Output, T::Output) -> T + Sync,\n    ID: Fn() -> T::Output + Sync,\n    T: Try + Send,\n{\n    type Folder = TryReduceFolder<'r, R, T>;\n    type Reducer = Self;\n    type Result = T;\n\n    fn split_at(self, _index: usize) -> (Self, Self, Self) {\n        (self, self, self)\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        TryReduceFolder {\n            reduce_op: self.reduce_op,\n            control: Continue((self.identity)()),\n            full: self.full,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.full.load(Ordering::Relaxed)\n    }\n}\n\nimpl<'r, R, ID, T> UnindexedConsumer<T> for TryReduceConsumer<'r, R, ID>\nwhere\n    R: Fn(T::Output, T::Output) -> T + Sync,\n    ID: Fn() -> T::Output + Sync,\n    T: Try + Send,\n{\n    fn split_off_left(&self) -> Self {\n        *self\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        *self\n    }\n}\n\nimpl<'r, R, ID, T> Reducer<T> for TryReduceConsumer<'r, R, ID>\nwhere\n    R: Fn(T::Output, T::Output) -> T + Sync,\n    T: Try,\n{\n    fn reduce(self, left: T, right: T) -> T {\n        match (left.branch(), right.branch()) {\n            (Continue(left), Continue(right)) => (self.reduce_op)(left, right),\n            (Break(r), _) | (_, Break(r)) => T::from_residual(r),\n        }\n    }\n}\n\nstruct TryReduceFolder<'r, R, T: Try> {\n    reduce_op: &'r R,\n    control: ControlFlow<T::Residual, T::Output>,\n    full: &'r AtomicBool,\n}\n\nimpl<'r, R, T> Folder<T> for TryReduceFolder<'r, R, T>\nwhere\n    R: Fn(T::Output, T::Output) -> T,\n    T: Try,\n{\n    type Result = T;\n\n    fn consume(mut self, item: T) -> Self {\n        let reduce_op = self.reduce_op;\n        self.control = match (self.control, item.branch()) {\n            (Continue(left), Continue(right)) => reduce_op(left, right).branch(),\n            (control @ Break(_), _) | (_, control @ Break(_)) => control,\n        };\n        if let Break(_) = self.control {\n            self.full.store(true, Ordering::Relaxed);\n        }\n        self\n    }\n\n    fn complete(self) -> T {\n        match self.control {\n            Continue(c) => T::from_output(c),\n            Break(r) => T::from_residual(r),\n        }\n    }\n\n    fn full(&self) -> bool {\n        match self.control {\n            Break(_) => true,\n            _ => self.full.load(Ordering::Relaxed),\n        }\n    }\n}\n"
  },
  {
    "path": "src/iter/try_reduce_with.rs",
    "content": "use super::plumbing::*;\nuse super::ParallelIterator;\nuse super::Try;\n\nuse std::ops::ControlFlow::{self, Break, Continue};\nuse std::sync::atomic::{AtomicBool, Ordering};\n\npub(super) fn try_reduce_with<PI, R, T>(pi: PI, reduce_op: R) -> Option<T>\nwhere\n    PI: ParallelIterator<Item = T>,\n    R: Fn(T::Output, T::Output) -> T + Sync,\n    T: Try + Send,\n{\n    let full = AtomicBool::new(false);\n    let consumer = TryReduceWithConsumer {\n        reduce_op: &reduce_op,\n        full: &full,\n    };\n    pi.drive_unindexed(consumer)\n}\n\nstruct TryReduceWithConsumer<'r, R> {\n    reduce_op: &'r R,\n    full: &'r AtomicBool,\n}\n\nimpl<'r, R> Copy for TryReduceWithConsumer<'r, R> {}\n\nimpl<'r, R> Clone for TryReduceWithConsumer<'r, R> {\n    fn clone(&self) -> Self {\n        *self\n    }\n}\n\nimpl<'r, R, T> Consumer<T> for TryReduceWithConsumer<'r, R>\nwhere\n    R: Fn(T::Output, T::Output) -> T + Sync,\n    T: Try + Send,\n{\n    type Folder = TryReduceWithFolder<'r, R, T>;\n    type Reducer = Self;\n    type Result = Option<T>;\n\n    fn split_at(self, _index: usize) -> (Self, Self, Self) {\n        (self, self, self)\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        TryReduceWithFolder {\n            reduce_op: self.reduce_op,\n            opt_control: None,\n            full: self.full,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.full.load(Ordering::Relaxed)\n    }\n}\n\nimpl<'r, R, T> UnindexedConsumer<T> for TryReduceWithConsumer<'r, R>\nwhere\n    R: Fn(T::Output, T::Output) -> T + Sync,\n    T: Try + Send,\n{\n    fn split_off_left(&self) -> Self {\n        *self\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        *self\n    }\n}\n\nimpl<'r, R, T> Reducer<Option<T>> for TryReduceWithConsumer<'r, R>\nwhere\n    R: Fn(T::Output, T::Output) -> T + Sync,\n    T: Try,\n{\n    fn reduce(self, left: Option<T>, right: Option<T>) -> Option<T> {\n        let reduce_op = self.reduce_op;\n        match (left, right) {\n            (Some(left), Some(right)) => match (left.branch(), right.branch()) {\n                (Continue(left), Continue(right)) => Some(reduce_op(left, right)),\n                (Break(r), _) | (_, Break(r)) => Some(T::from_residual(r)),\n            },\n            (None, x) | (x, None) => x,\n        }\n    }\n}\n\nstruct TryReduceWithFolder<'r, R, T: Try> {\n    reduce_op: &'r R,\n    opt_control: Option<ControlFlow<T::Residual, T::Output>>,\n    full: &'r AtomicBool,\n}\n\nimpl<'r, R, T> Folder<T> for TryReduceWithFolder<'r, R, T>\nwhere\n    R: Fn(T::Output, T::Output) -> T,\n    T: Try,\n{\n    type Result = Option<T>;\n\n    fn consume(mut self, item: T) -> Self {\n        let reduce_op = self.reduce_op;\n        let control = match (self.opt_control, item.branch()) {\n            (Some(Continue(left)), Continue(right)) => reduce_op(left, right).branch(),\n            (Some(control @ Break(_)), _) | (_, control) => control,\n        };\n        if let Break(_) = control {\n            self.full.store(true, Ordering::Relaxed)\n        }\n        self.opt_control = Some(control);\n        self\n    }\n\n    fn complete(self) -> Option<T> {\n        match self.opt_control {\n            Some(Continue(c)) => Some(T::from_output(c)),\n            Some(Break(r)) => Some(T::from_residual(r)),\n            None => None,\n        }\n    }\n\n    fn full(&self) -> bool {\n        match self.opt_control {\n            Some(Break(_)) => true,\n            _ => self.full.load(Ordering::Relaxed),\n        }\n    }\n}\n"
  },
  {
    "path": "src/iter/unzip.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\n/// This trait abstracts the different ways we can \"unzip\" one parallel\n/// iterator into two distinct consumers, which we can handle almost\n/// identically apart from how to process the individual items.\ntrait UnzipOp<T>: Sync + Send {\n    /// The type of item expected by the left consumer.\n    type Left: Send;\n\n    /// The type of item expected by the right consumer.\n    type Right: Send;\n\n    /// Consumes one item and feeds it to one or both of the underlying folders.\n    fn consume<FA, FB>(&self, item: T, left: FA, right: FB) -> (FA, FB)\n    where\n        FA: Folder<Self::Left>,\n        FB: Folder<Self::Right>;\n\n    /// Reports whether this op may support indexed consumers.\n    /// - e.g. true for `unzip` where the item count passed through directly.\n    /// - e.g. false for `partition` where the sorting is not yet known.\n    fn indexable() -> bool {\n        false\n    }\n}\n\n/// Runs an unzip-like operation into default `ParallelExtend` collections.\nfn execute<I, OP, FromA, FromB>(pi: I, op: OP) -> (FromA, FromB)\nwhere\n    I: ParallelIterator,\n    OP: UnzipOp<I::Item>,\n    FromA: Default + Send + ParallelExtend<OP::Left>,\n    FromB: Default + Send + ParallelExtend<OP::Right>,\n{\n    let mut a = FromA::default();\n    let mut b = FromB::default();\n    execute_into(&mut a, &mut b, pi, op);\n    (a, b)\n}\n\n/// Runs an unzip-like operation into `ParallelExtend` collections.\nfn execute_into<I, OP, FromA, FromB>(a: &mut FromA, b: &mut FromB, pi: I, op: OP)\nwhere\n    I: ParallelIterator,\n    OP: UnzipOp<I::Item>,\n    FromA: Send + ParallelExtend<OP::Left>,\n    FromB: Send + ParallelExtend<OP::Right>,\n{\n    // We have no idea what the consumers will look like for these\n    // collections' `par_extend`, but we can intercept them in our own\n    // `drive_unindexed`.  Start with the left side, type `A`:\n    let iter = UnzipA { base: pi, op, b };\n    a.par_extend(iter);\n}\n\n/// Unzips the items of a parallel iterator into a pair of arbitrary\n/// `ParallelExtend` containers.\n///\n/// This is called by `ParallelIterator::unzip`.\npub(super) fn unzip<I, A, B, FromA, FromB>(pi: I) -> (FromA, FromB)\nwhere\n    I: ParallelIterator<Item = (A, B)>,\n    FromA: Default + Send + ParallelExtend<A>,\n    FromB: Default + Send + ParallelExtend<B>,\n    A: Send,\n    B: Send,\n{\n    execute(pi, Unzip)\n}\n\n/// Unzips an `IndexedParallelIterator` into two arbitrary `Consumer`s.\n///\n/// This is called by `super::collect::unzip_into_vecs`.\npub(super) fn unzip_indexed<I, A, B, CA, CB>(pi: I, left: CA, right: CB) -> (CA::Result, CB::Result)\nwhere\n    I: IndexedParallelIterator<Item = (A, B)>,\n    CA: Consumer<A>,\n    CB: Consumer<B>,\n    A: Send,\n    B: Send,\n{\n    let consumer = UnzipConsumer {\n        op: &Unzip,\n        left,\n        right,\n    };\n    pi.drive(consumer)\n}\n\n/// An `UnzipOp` that splits a tuple directly into the two consumers.\nstruct Unzip;\n\nimpl<A: Send, B: Send> UnzipOp<(A, B)> for Unzip {\n    type Left = A;\n    type Right = B;\n\n    fn consume<FA, FB>(&self, item: (A, B), left: FA, right: FB) -> (FA, FB)\n    where\n        FA: Folder<A>,\n        FB: Folder<B>,\n    {\n        (left.consume(item.0), right.consume(item.1))\n    }\n\n    fn indexable() -> bool {\n        true\n    }\n}\n\n/// Partitions the items of a parallel iterator into a pair of arbitrary\n/// `ParallelExtend` containers.\n///\n/// This is called by `ParallelIterator::partition`.\npub(super) fn partition<I, A, B, P>(pi: I, predicate: P) -> (A, B)\nwhere\n    I: ParallelIterator,\n    A: Default + Send + ParallelExtend<I::Item>,\n    B: Default + Send + ParallelExtend<I::Item>,\n    P: Fn(&I::Item) -> bool + Sync + Send,\n{\n    execute(pi, Partition { predicate })\n}\n\n/// An `UnzipOp` that routes items depending on a predicate function.\nstruct Partition<P> {\n    predicate: P,\n}\n\nimpl<P, T> UnzipOp<T> for Partition<P>\nwhere\n    P: Fn(&T) -> bool + Sync + Send,\n    T: Send,\n{\n    type Left = T;\n    type Right = T;\n\n    fn consume<FA, FB>(&self, item: T, left: FA, right: FB) -> (FA, FB)\n    where\n        FA: Folder<T>,\n        FB: Folder<T>,\n    {\n        if (self.predicate)(&item) {\n            (left.consume(item), right)\n        } else {\n            (left, right.consume(item))\n        }\n    }\n}\n\n/// Partitions and maps the items of a parallel iterator into a pair of\n/// arbitrary `ParallelExtend` containers.\n///\n/// This called by `ParallelIterator::partition_map`.\npub(super) fn partition_map<I, A, B, P, L, R>(pi: I, predicate: P) -> (A, B)\nwhere\n    I: ParallelIterator,\n    A: Default + Send + ParallelExtend<L>,\n    B: Default + Send + ParallelExtend<R>,\n    P: Fn(I::Item) -> Either<L, R> + Sync + Send,\n    L: Send,\n    R: Send,\n{\n    execute(pi, PartitionMap { predicate })\n}\n\n/// An `UnzipOp` that routes items depending on how they are mapped `Either`.\nstruct PartitionMap<P> {\n    predicate: P,\n}\n\nimpl<P, L, R, T> UnzipOp<T> for PartitionMap<P>\nwhere\n    P: Fn(T) -> Either<L, R> + Sync + Send,\n    L: Send,\n    R: Send,\n{\n    type Left = L;\n    type Right = R;\n\n    fn consume<FA, FB>(&self, item: T, left: FA, right: FB) -> (FA, FB)\n    where\n        FA: Folder<L>,\n        FB: Folder<R>,\n    {\n        match (self.predicate)(item) {\n            Either::Left(item) => (left.consume(item), right),\n            Either::Right(item) => (left, right.consume(item)),\n        }\n    }\n}\n\n/// A fake iterator to intercept the `Consumer` for type `A`.\nstruct UnzipA<'b, I, OP, FromB> {\n    base: I,\n    op: OP,\n    b: &'b mut FromB,\n}\n\nimpl<'b, I, OP, FromB> ParallelIterator for UnzipA<'b, I, OP, FromB>\nwhere\n    I: ParallelIterator,\n    OP: UnzipOp<I::Item>,\n    FromB: Send + ParallelExtend<OP::Right>,\n{\n    type Item = OP::Left;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let mut result = None;\n        {\n            // Now it's time to find the consumer for type `B`\n            let iter = UnzipB {\n                base: self.base,\n                op: self.op,\n                left_consumer: consumer,\n                left_result: &mut result,\n            };\n            self.b.par_extend(iter);\n        }\n        // NB: If for some reason `b.par_extend` doesn't actually drive the\n        // iterator, then we won't have a result for the left side to return\n        // at all.  We can't fake an arbitrary consumer's result, so panic.\n        result.expect(\"unzip consumers didn't execute!\")\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        if OP::indexable() {\n            self.base.opt_len()\n        } else {\n            None\n        }\n    }\n}\n\n/// A fake iterator to intercept the `Consumer` for type `B`.\nstruct UnzipB<'r, I, OP, CA>\nwhere\n    I: ParallelIterator,\n    OP: UnzipOp<I::Item>,\n    CA: UnindexedConsumer<OP::Left>,\n{\n    base: I,\n    op: OP,\n    left_consumer: CA,\n    left_result: &'r mut Option<CA::Result>,\n}\n\nimpl<'r, I, OP, CA> ParallelIterator for UnzipB<'r, I, OP, CA>\nwhere\n    I: ParallelIterator,\n    OP: UnzipOp<I::Item>,\n    CA: UnindexedConsumer<OP::Left>,\n{\n    type Item = OP::Right;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        // Now that we have two consumers, we can unzip the real iterator.\n        let consumer = UnzipConsumer {\n            op: &self.op,\n            left: self.left_consumer,\n            right: consumer,\n        };\n\n        let result = self.base.drive_unindexed(consumer);\n        *self.left_result = Some(result.0);\n        result.1\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        if OP::indexable() {\n            self.base.opt_len()\n        } else {\n            None\n        }\n    }\n}\n\n/// `Consumer` that unzips into two other `Consumer`s\nstruct UnzipConsumer<'a, OP, CA, CB> {\n    op: &'a OP,\n    left: CA,\n    right: CB,\n}\n\nimpl<'a, T, OP, CA, CB> Consumer<T> for UnzipConsumer<'a, OP, CA, CB>\nwhere\n    OP: UnzipOp<T>,\n    CA: Consumer<OP::Left>,\n    CB: Consumer<OP::Right>,\n{\n    type Folder = UnzipFolder<'a, OP, CA::Folder, CB::Folder>;\n    type Reducer = UnzipReducer<CA::Reducer, CB::Reducer>;\n    type Result = (CA::Result, CB::Result);\n\n    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {\n        let (left1, left2, left_reducer) = self.left.split_at(index);\n        let (right1, right2, right_reducer) = self.right.split_at(index);\n\n        (\n            UnzipConsumer {\n                op: self.op,\n                left: left1,\n                right: right1,\n            },\n            UnzipConsumer {\n                op: self.op,\n                left: left2,\n                right: right2,\n            },\n            UnzipReducer {\n                left: left_reducer,\n                right: right_reducer,\n            },\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        UnzipFolder {\n            op: self.op,\n            left: self.left.into_folder(),\n            right: self.right.into_folder(),\n        }\n    }\n\n    fn full(&self) -> bool {\n        // don't stop until everyone is full\n        self.left.full() && self.right.full()\n    }\n}\n\nimpl<'a, T, OP, CA, CB> UnindexedConsumer<T> for UnzipConsumer<'a, OP, CA, CB>\nwhere\n    OP: UnzipOp<T>,\n    CA: UnindexedConsumer<OP::Left>,\n    CB: UnindexedConsumer<OP::Right>,\n{\n    fn split_off_left(&self) -> Self {\n        UnzipConsumer {\n            op: self.op,\n            left: self.left.split_off_left(),\n            right: self.right.split_off_left(),\n        }\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        UnzipReducer {\n            left: self.left.to_reducer(),\n            right: self.right.to_reducer(),\n        }\n    }\n}\n\n/// `Folder` that unzips into two other `Folder`s\nstruct UnzipFolder<'a, OP, FA, FB> {\n    op: &'a OP,\n    left: FA,\n    right: FB,\n}\n\nimpl<'a, T, OP, FA, FB> Folder<T> for UnzipFolder<'a, OP, FA, FB>\nwhere\n    OP: UnzipOp<T>,\n    FA: Folder<OP::Left>,\n    FB: Folder<OP::Right>,\n{\n    type Result = (FA::Result, FB::Result);\n\n    fn consume(self, item: T) -> Self {\n        let (left, right) = self.op.consume(item, self.left, self.right);\n        UnzipFolder {\n            op: self.op,\n            left,\n            right,\n        }\n    }\n\n    fn complete(self) -> Self::Result {\n        (self.left.complete(), self.right.complete())\n    }\n\n    fn full(&self) -> bool {\n        // don't stop until everyone is full\n        self.left.full() && self.right.full()\n    }\n}\n\n/// `Reducer` that unzips into two other `Reducer`s\nstruct UnzipReducer<RA, RB> {\n    left: RA,\n    right: RB,\n}\n\nimpl<A, B, RA, RB> Reducer<(A, B)> for UnzipReducer<RA, RB>\nwhere\n    RA: Reducer<A>,\n    RB: Reducer<B>,\n{\n    fn reduce(self, left: (A, B), right: (A, B)) -> (A, B) {\n        (\n            self.left.reduce(left.0, right.0),\n            self.right.reduce(left.1, right.1),\n        )\n    }\n}\n\nimpl<A, B, FromA, FromB> ParallelExtend<(A, B)> for (FromA, FromB)\nwhere\n    A: Send,\n    B: Send,\n    FromA: Send + ParallelExtend<A>,\n    FromB: Send + ParallelExtend<B>,\n{\n    fn par_extend<I>(&mut self, pi: I)\n    where\n        I: IntoParallelIterator<Item = (A, B)>,\n    {\n        execute_into(&mut self.0, &mut self.1, pi.into_par_iter(), Unzip);\n    }\n}\n\nimpl<L, R, A, B> ParallelExtend<Either<L, R>> for (A, B)\nwhere\n    L: Send,\n    R: Send,\n    A: Send + ParallelExtend<L>,\n    B: Send + ParallelExtend<R>,\n{\n    fn par_extend<I>(&mut self, pi: I)\n    where\n        I: IntoParallelIterator<Item = Either<L, R>>,\n    {\n        execute_into(&mut self.0, &mut self.1, pi.into_par_iter(), UnEither);\n    }\n}\n\n/// An `UnzipOp` that routes items depending on their `Either` variant.\nstruct UnEither;\n\nimpl<L, R> UnzipOp<Either<L, R>> for UnEither\nwhere\n    L: Send,\n    R: Send,\n{\n    type Left = L;\n    type Right = R;\n\n    fn consume<FL, FR>(&self, item: Either<L, R>, left: FL, right: FR) -> (FL, FR)\n    where\n        FL: Folder<L>,\n        FR: Folder<R>,\n    {\n        match item {\n            Either::Left(item) => (left.consume(item), right),\n            Either::Right(item) => (left, right.consume(item)),\n        }\n    }\n}\n\nimpl<A, B, FromA, FromB> FromParallelIterator<(A, B)> for (FromA, FromB)\nwhere\n    A: Send,\n    B: Send,\n    FromA: Send + FromParallelIterator<A>,\n    FromB: Send + FromParallelIterator<B>,\n{\n    fn from_par_iter<I>(pi: I) -> Self\n    where\n        I: IntoParallelIterator<Item = (A, B)>,\n    {\n        let (a, b): (Collector<FromA>, Collector<FromB>) = pi.into_par_iter().unzip();\n        (a.result.unwrap(), b.result.unwrap())\n    }\n}\n\nimpl<L, R, A, B> FromParallelIterator<Either<L, R>> for (A, B)\nwhere\n    L: Send,\n    R: Send,\n    A: Send + FromParallelIterator<L>,\n    B: Send + FromParallelIterator<R>,\n{\n    fn from_par_iter<I>(pi: I) -> Self\n    where\n        I: IntoParallelIterator<Item = Either<L, R>>,\n    {\n        fn identity<T>(x: T) -> T {\n            x\n        }\n\n        let (a, b): (Collector<A>, Collector<B>) = pi.into_par_iter().partition_map(identity);\n        (a.result.unwrap(), b.result.unwrap())\n    }\n}\n\n/// Shim to implement a one-time `ParallelExtend` using `FromParallelIterator`.\nstruct Collector<FromT> {\n    result: Option<FromT>,\n}\n\nimpl<FromT> Default for Collector<FromT> {\n    fn default() -> Self {\n        Collector { result: None }\n    }\n}\n\nimpl<T, FromT> ParallelExtend<T> for Collector<FromT>\nwhere\n    T: Send,\n    FromT: Send + FromParallelIterator<T>,\n{\n    fn par_extend<I>(&mut self, pi: I)\n    where\n        I: IntoParallelIterator<Item = T>,\n    {\n        debug_assert!(self.result.is_none());\n        self.result = Some(pi.into_par_iter().collect());\n    }\n}\n"
  },
  {
    "path": "src/iter/update.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\n\n/// `Update` is an iterator that mutates the elements of an\n/// underlying iterator before they are yielded.\n///\n/// This struct is created by the [`update()`] method on [`ParallelIterator`]\n///\n/// [`update()`]: ParallelIterator::update()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Clone)]\npub struct Update<I, F> {\n    base: I,\n    update_op: F,\n}\n\nimpl<I: Debug, F> Debug for Update<I, F> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"Update\").field(\"base\", &self.base).finish()\n    }\n}\n\nimpl<I, F> Update<I, F> {\n    /// Creates a new `Update` iterator.\n    pub(super) fn new(base: I, update_op: F) -> Self {\n        Update { base, update_op }\n    }\n}\n\nimpl<I, F> ParallelIterator for Update<I, F>\nwhere\n    I: ParallelIterator,\n    F: Fn(&mut I::Item) + Send + Sync,\n{\n    type Item = I::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let consumer1 = UpdateConsumer::new(consumer, &self.update_op);\n        self.base.drive_unindexed(consumer1)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        self.base.opt_len()\n    }\n}\n\nimpl<I, F> IndexedParallelIterator for Update<I, F>\nwhere\n    I: IndexedParallelIterator,\n    F: Fn(&mut I::Item) + Send + Sync,\n{\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        let consumer1 = UpdateConsumer::new(consumer, &self.update_op);\n        self.base.drive(consumer1)\n    }\n\n    fn len(&self) -> usize {\n        self.base.len()\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        return self.base.with_producer(Callback {\n            callback,\n            update_op: self.update_op,\n        });\n\n        struct Callback<CB, F> {\n            callback: CB,\n            update_op: F,\n        }\n\n        impl<T, F, CB> ProducerCallback<T> for Callback<CB, F>\n        where\n            CB: ProducerCallback<T>,\n            F: Fn(&mut T) + Send + Sync,\n        {\n            type Output = CB::Output;\n\n            fn callback<P>(self, base: P) -> CB::Output\n            where\n                P: Producer<Item = T>,\n            {\n                let producer = UpdateProducer {\n                    base,\n                    update_op: &self.update_op,\n                };\n                self.callback.callback(producer)\n            }\n        }\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n\nstruct UpdateProducer<'f, P, F> {\n    base: P,\n    update_op: &'f F,\n}\n\nimpl<'f, P, F> Producer for UpdateProducer<'f, P, F>\nwhere\n    P: Producer,\n    F: Fn(&mut P::Item) + Send + Sync,\n{\n    type Item = P::Item;\n    type IntoIter = UpdateSeq<P::IntoIter, &'f F>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        UpdateSeq {\n            base: self.base.into_iter(),\n            update_op: self.update_op,\n        }\n    }\n\n    fn min_len(&self) -> usize {\n        self.base.min_len()\n    }\n    fn max_len(&self) -> usize {\n        self.base.max_len()\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let (left, right) = self.base.split_at(index);\n        (\n            UpdateProducer {\n                base: left,\n                update_op: self.update_op,\n            },\n            UpdateProducer {\n                base: right,\n                update_op: self.update_op,\n            },\n        )\n    }\n\n    fn fold_with<G>(self, folder: G) -> G\n    where\n        G: Folder<Self::Item>,\n    {\n        let folder1 = UpdateFolder {\n            base: folder,\n            update_op: self.update_op,\n        };\n        self.base.fold_with(folder1).base\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Consumer implementation\n\nstruct UpdateConsumer<'f, C, F> {\n    base: C,\n    update_op: &'f F,\n}\n\nimpl<'f, C, F> UpdateConsumer<'f, C, F> {\n    fn new(base: C, update_op: &'f F) -> Self {\n        UpdateConsumer { base, update_op }\n    }\n}\n\nimpl<'f, T, C, F> Consumer<T> for UpdateConsumer<'f, C, F>\nwhere\n    C: Consumer<T>,\n    F: Fn(&mut T) + Send + Sync,\n{\n    type Folder = UpdateFolder<'f, C::Folder, F>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            UpdateConsumer::new(left, self.update_op),\n            UpdateConsumer::new(right, self.update_op),\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        UpdateFolder {\n            base: self.base.into_folder(),\n            update_op: self.update_op,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\nimpl<'f, T, C, F> UnindexedConsumer<T> for UpdateConsumer<'f, C, F>\nwhere\n    C: UnindexedConsumer<T>,\n    F: Fn(&mut T) + Send + Sync,\n{\n    fn split_off_left(&self) -> Self {\n        UpdateConsumer::new(self.base.split_off_left(), self.update_op)\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n\nstruct UpdateFolder<'f, C, F> {\n    base: C,\n    update_op: &'f F,\n}\n\nfn apply<T>(update_op: impl Fn(&mut T)) -> impl Fn(T) -> T {\n    move |mut item| {\n        update_op(&mut item);\n        item\n    }\n}\n\nimpl<'f, T, C, F> Folder<T> for UpdateFolder<'f, C, F>\nwhere\n    C: Folder<T>,\n    F: Fn(&mut T),\n{\n    type Result = C::Result;\n\n    fn consume(self, mut item: T) -> Self {\n        (self.update_op)(&mut item);\n\n        UpdateFolder {\n            base: self.base.consume(item),\n            update_op: self.update_op,\n        }\n    }\n\n    fn consume_iter<I>(mut self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = T>,\n    {\n        let update_op = self.update_op;\n        self.base = self\n            .base\n            .consume_iter(iter.into_iter().map(apply(update_op)));\n        self\n    }\n\n    fn complete(self) -> C::Result {\n        self.base.complete()\n    }\n\n    fn full(&self) -> bool {\n        self.base.full()\n    }\n}\n\n/// Standard Update adaptor, based on `itertools::adaptors::Update`\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\nstruct UpdateSeq<I, F> {\n    base: I,\n    update_op: F,\n}\n\nimpl<I, F> Iterator for UpdateSeq<I, F>\nwhere\n    I: Iterator,\n    F: Fn(&mut I::Item),\n{\n    type Item = I::Item;\n\n    fn next(&mut self) -> Option<Self::Item> {\n        let mut v = self.base.next()?;\n        (self.update_op)(&mut v);\n        Some(v)\n    }\n\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        self.base.size_hint()\n    }\n\n    fn fold<Acc, G>(self, init: Acc, g: G) -> Acc\n    where\n        G: FnMut(Acc, Self::Item) -> Acc,\n    {\n        self.base.map(apply(self.update_op)).fold(init, g)\n    }\n\n    // if possible, re-use inner iterator specializations in collect\n    fn collect<C>(self) -> C\n    where\n        C: ::std::iter::FromIterator<Self::Item>,\n    {\n        self.base.map(apply(self.update_op)).collect()\n    }\n}\n\nimpl<I, F> ExactSizeIterator for UpdateSeq<I, F>\nwhere\n    I: ExactSizeIterator,\n    F: Fn(&mut I::Item),\n{\n}\n\nimpl<I, F> DoubleEndedIterator for UpdateSeq<I, F>\nwhere\n    I: DoubleEndedIterator,\n    F: Fn(&mut I::Item),\n{\n    fn next_back(&mut self) -> Option<Self::Item> {\n        let mut v = self.base.next_back()?;\n        (self.update_op)(&mut v);\n        Some(v)\n    }\n}\n"
  },
  {
    "path": "src/iter/walk_tree.rs",
    "content": "use crate::iter::plumbing::{bridge_unindexed, Folder, UnindexedConsumer, UnindexedProducer};\nuse crate::prelude::*;\nuse std::iter::once;\n\n#[derive(Debug)]\nstruct WalkTreePrefixProducer<'b, S, B> {\n    to_explore: Vec<S>, // nodes (and subtrees) we have to process\n    seen: Vec<S>,       // nodes which have already been explored\n    children_of: &'b B, // function generating children\n}\n\nimpl<S, B, I> UnindexedProducer for WalkTreePrefixProducer<'_, S, B>\nwhere\n    S: Send,\n    B: Fn(&S) -> I + Send + Sync,\n    I: IntoIterator<Item = S, IntoIter: DoubleEndedIterator>,\n{\n    type Item = S;\n\n    fn split(mut self) -> (Self, Option<Self>) {\n        // explore while front is of size one.\n        while self.to_explore.len() == 1 {\n            let front_node = self.to_explore.pop().unwrap();\n            self.to_explore\n                .extend((self.children_of)(&front_node).into_iter().rev());\n            self.seen.push(front_node);\n        }\n        // now take half of the front.\n        let right_children = split_vec(&mut self.to_explore);\n        let right = right_children\n            .map(|mut c| {\n                std::mem::swap(&mut c, &mut self.to_explore);\n                WalkTreePrefixProducer {\n                    to_explore: c,\n                    seen: Vec::new(),\n                    children_of: self.children_of,\n                }\n            })\n            .or_else(|| {\n                // we can still try to divide 'seen'\n                let right_seen = split_vec(&mut self.seen);\n                right_seen.map(|s| WalkTreePrefixProducer {\n                    to_explore: Default::default(),\n                    seen: s,\n                    children_of: self.children_of,\n                })\n            });\n        (self, right)\n    }\n\n    fn fold_with<F>(mut self, mut folder: F) -> F\n    where\n        F: Folder<Self::Item>,\n    {\n        // start by consuming everything seen\n        folder = folder.consume_iter(self.seen);\n        if folder.full() {\n            return folder;\n        }\n        // now do all remaining explorations\n        while let Some(e) = self.to_explore.pop() {\n            self.to_explore\n                .extend((self.children_of)(&e).into_iter().rev());\n            folder = folder.consume(e);\n            if folder.full() {\n                return folder;\n            }\n        }\n        folder\n    }\n}\n\n/// ParallelIterator for arbitrary tree-shaped patterns.\n/// Returned by the [`walk_tree_prefix()`] function.\n#[derive(Debug)]\npub struct WalkTreePrefix<S, B> {\n    initial_state: S,\n    children_of: B,\n}\n\nimpl<S, B, I> ParallelIterator for WalkTreePrefix<S, B>\nwhere\n    S: Send,\n    B: Fn(&S) -> I + Send + Sync,\n    I: IntoIterator<Item = S, IntoIter: DoubleEndedIterator>,\n{\n    type Item = S;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let producer = WalkTreePrefixProducer {\n            to_explore: once(self.initial_state).collect(),\n            seen: Vec::new(),\n            children_of: &self.children_of,\n        };\n        bridge_unindexed(producer, consumer)\n    }\n}\n\n/// Create a tree-like prefix parallel iterator from an initial root node.\n/// The `children_of` function should take a node and return an iterator over its child nodes.\n/// The best parallelization is obtained when the tree is balanced\n/// but we should also be able to handle harder cases.\n///\n/// # Ordering\n///\n/// This function guarantees a prefix ordering. See also [`walk_tree_postfix`],\n/// which guarantees a postfix order.\n/// If you don't care about ordering, you should use [`walk_tree`],\n/// which will use whatever is believed to be fastest.\n/// For example a perfect binary tree of 7 nodes will reduced in the following order:\n///\n/// ```text\n///      a\n///     / \\\n///    /   \\\n///   b     c\n///  / \\   / \\\n/// d   e f   g\n///\n/// reduced as a,b,d,e,c,f,g\n///\n/// ```\n///\n/// # Example\n///\n/// ```text\n///      4\n///     / \\\n///    /   \\\n///   2     3\n///        / \\\n///       1   2\n/// ```\n///\n/// ```\n/// use rayon::iter::walk_tree_prefix;\n/// use rayon::prelude::*;\n///\n/// let par_iter = walk_tree_prefix(4, |&e| {\n///     if e <= 2 {\n///         Vec::new()\n///     } else {\n///         vec![e / 2, e / 2 + 1]\n///     }\n/// });\n/// assert_eq!(par_iter.sum::<u32>(), 12);\n/// ```\n///\n/// # Example\n///\n/// ```\n/// use rayon::prelude::*;\n/// use rayon::iter::walk_tree_prefix;\n///\n/// struct Node {\n///     content: u32,\n///     left: Option<Box<Node>>,\n///     right: Option<Box<Node>>,\n/// }\n///\n/// // Here we loop on the following tree:\n/// //\n/// //       10\n/// //      /  \\\n/// //     /    \\\n/// //    3     14\n/// //            \\\n/// //             \\\n/// //              18\n///\n/// let root = Node {\n///     content: 10,\n///     left: Some(Box::new(Node {\n///         content: 3,\n///         left: None,\n///         right: None,\n///     })),\n///     right: Some(Box::new(Node {\n///         content: 14,\n///         left: None,\n///         right: Some(Box::new(Node {\n///             content: 18,\n///             left: None,\n///             right: None,\n///         })),\n///     })),\n/// };\n///\n/// let mut v: Vec<u32> = walk_tree_prefix(&root, |r| {\n///     r.left\n///         .as_ref()\n///         .into_iter()\n///         .chain(r.right.as_ref())\n///         .map(|n| &**n)\n/// })\n/// .map(|node| node.content)\n/// .collect();\n/// assert_eq!(v, vec![10, 3, 14, 18]);\n/// ```\n///\npub fn walk_tree_prefix<S, B, I>(root: S, children_of: B) -> WalkTreePrefix<S, B>\nwhere\n    S: Send,\n    B: Fn(&S) -> I + Send + Sync,\n    I: IntoIterator<Item = S, IntoIter: DoubleEndedIterator>,\n{\n    WalkTreePrefix {\n        initial_state: root,\n        children_of,\n    }\n}\n\n// post fix\n\n#[derive(Debug)]\nstruct WalkTreePostfixProducer<'b, S, B> {\n    to_explore: Vec<S>, // nodes (and subtrees) we have to process\n    seen: Vec<S>,       // nodes which have already been explored\n    children_of: &'b B, // function generating children\n}\n\nimpl<S, B, I> UnindexedProducer for WalkTreePostfixProducer<'_, S, B>\nwhere\n    S: Send,\n    B: Fn(&S) -> I + Send + Sync,\n    I: IntoIterator<Item = S>,\n{\n    type Item = S;\n\n    fn split(mut self) -> (Self, Option<Self>) {\n        // explore while front is of size one.\n        while self.to_explore.len() == 1 {\n            let front_node = self.to_explore.pop().unwrap();\n            self.to_explore\n                .extend((self.children_of)(&front_node).into_iter());\n            self.seen.push(front_node);\n        }\n        // now take half of the front.\n        let right_children = split_vec(&mut self.to_explore);\n        let right = right_children\n            .map(|c| {\n                let right_seen = std::mem::take(&mut self.seen); // postfix -> upper nodes are processed last\n                WalkTreePostfixProducer {\n                    to_explore: c,\n                    seen: right_seen,\n                    children_of: self.children_of,\n                }\n            })\n            .or_else(|| {\n                // we can still try to divide 'seen'\n                let right_seen = split_vec(&mut self.seen);\n                right_seen.map(|mut s| {\n                    std::mem::swap(&mut self.seen, &mut s);\n                    WalkTreePostfixProducer {\n                        to_explore: Default::default(),\n                        seen: s,\n                        children_of: self.children_of,\n                    }\n                })\n            });\n        (self, right)\n    }\n\n    fn fold_with<F>(self, mut folder: F) -> F\n    where\n        F: Folder<Self::Item>,\n    {\n        // now do all remaining explorations\n        for e in self.to_explore {\n            folder = consume_rec_postfix(&self.children_of, e, folder);\n            if folder.full() {\n                return folder;\n            }\n        }\n        // end by consuming everything seen\n        folder.consume_iter(self.seen.into_iter().rev())\n    }\n}\n\nfn consume_rec_postfix<F, S, B, I>(children_of: &B, s: S, mut folder: F) -> F\nwhere\n    F: Folder<S>,\n    B: Fn(&S) -> I,\n    I: IntoIterator<Item = S>,\n{\n    let children = (children_of)(&s).into_iter();\n    for child in children {\n        folder = consume_rec_postfix(children_of, child, folder);\n        if folder.full() {\n            return folder;\n        }\n    }\n    folder.consume(s)\n}\n\n/// ParallelIterator for arbitrary tree-shaped patterns.\n/// Returned by the [`walk_tree_postfix()`] function.\n#[derive(Debug)]\npub struct WalkTreePostfix<S, B> {\n    initial_state: S,\n    children_of: B,\n}\n\nimpl<S, B, I> ParallelIterator for WalkTreePostfix<S, B>\nwhere\n    S: Send,\n    B: Fn(&S) -> I + Send + Sync,\n    I: IntoIterator<Item = S>,\n{\n    type Item = S;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let producer = WalkTreePostfixProducer {\n            to_explore: once(self.initial_state).collect(),\n            seen: Vec::new(),\n            children_of: &self.children_of,\n        };\n        bridge_unindexed(producer, consumer)\n    }\n}\n\n/// Divide given vector in two equally sized vectors.\n/// Return `None` if initial size is <=1.\n/// We return the first half and keep the last half in `v`.\nfn split_vec<T>(v: &mut Vec<T>) -> Option<Vec<T>> {\n    if v.len() <= 1 {\n        None\n    } else {\n        let n = v.len() / 2;\n        Some(v.split_off(n))\n    }\n}\n\n/// Create a tree like postfix parallel iterator from an initial root node.\n/// The `children_of` function should take a node and iterate on all of its child nodes.\n/// The best parallelization is obtained when the tree is balanced\n/// but we should also be able to handle harder cases.\n///\n/// # Ordering\n///\n/// This function guarantees a postfix ordering. See also [`walk_tree_prefix`] which guarantees a\n/// prefix order. If you don't care about ordering, you should use [`walk_tree`], which will use\n/// whatever is believed to be fastest.\n///\n/// Between siblings, children are reduced in order -- that is first children are reduced first.\n///\n/// For example a perfect binary tree of 7 nodes will reduced in the following order:\n///\n/// ```text\n///      a\n///     / \\\n///    /   \\\n///   b     c\n///  / \\   / \\\n/// d   e f   g\n///\n/// reduced as d,e,b,f,g,c,a\n///\n/// ```\n///\n/// # Example\n///\n/// ```text\n///      4\n///     / \\\n///    /   \\\n///   2     3\n///        / \\\n///       1   2\n/// ```\n///\n/// ```\n/// use rayon::iter::walk_tree_postfix;\n/// use rayon::prelude::*;\n///\n/// let par_iter = walk_tree_postfix(4, |&e| {\n///     if e <= 2 {\n///         Vec::new()\n///     } else {\n///         vec![e / 2, e / 2 + 1]\n///     }\n/// });\n/// assert_eq!(par_iter.sum::<u32>(), 12);\n/// ```\n///\n/// # Example\n///\n/// ```\n/// use rayon::prelude::*;\n/// use rayon::iter::walk_tree_postfix;\n///\n/// struct Node {\n///     content: u32,\n///     left: Option<Box<Node>>,\n///     right: Option<Box<Node>>,\n/// }\n///\n/// // Here we loop on the following tree:\n/// //\n/// //       10\n/// //      /  \\\n/// //     /    \\\n/// //    3     14\n/// //            \\\n/// //             \\\n/// //              18\n///\n/// let root = Node {\n///     content: 10,\n///     left: Some(Box::new(Node {\n///         content: 3,\n///         left: None,\n///         right: None,\n///     })),\n///     right: Some(Box::new(Node {\n///         content: 14,\n///         left: None,\n///         right: Some(Box::new(Node {\n///             content: 18,\n///             left: None,\n///             right: None,\n///         })),\n///     })),\n/// };\n///\n/// let mut v: Vec<u32> = walk_tree_postfix(&root, |r| {\n///     r.left\n///         .as_ref()\n///         .into_iter()\n///         .chain(r.right.as_ref())\n///         .map(|n| &**n)\n/// })\n/// .map(|node| node.content)\n/// .collect();\n/// assert_eq!(v, vec![3, 18, 14, 10]);\n/// ```\n///\npub fn walk_tree_postfix<S, B, I>(root: S, children_of: B) -> WalkTreePostfix<S, B>\nwhere\n    S: Send,\n    B: Fn(&S) -> I + Send + Sync,\n    I: IntoIterator<Item = S>,\n{\n    WalkTreePostfix {\n        initial_state: root,\n        children_of,\n    }\n}\n\n/// ParallelIterator for arbitrary tree-shaped patterns.\n/// Returned by the [`walk_tree()`] function.\n#[derive(Debug)]\npub struct WalkTree<S, B>(WalkTreePostfix<S, B>);\n\n/// Create a tree like parallel iterator from an initial root node.\n/// The `children_of` function should take a node and iterate on all of its child nodes.\n/// The best parallelization is obtained when the tree is balanced\n/// but we should also be able to handle harder cases.\n///\n/// # Ordering\n///\n/// This function does not guarantee any ordering but will\n/// use whatever algorithm is thought to achieve the fastest traversal.\n/// See also [`walk_tree_prefix`] which guarantees a\n/// prefix order and [`walk_tree_postfix`] which guarantees a postfix order.\n///\n/// # Example\n///\n/// ```text\n///      4\n///     / \\\n///    /   \\\n///   2     3\n///        / \\\n///       1   2\n/// ```\n///\n/// ```\n/// use rayon::iter::walk_tree;\n/// use rayon::prelude::*;\n///\n/// let par_iter = walk_tree(4, |&e| {\n///     if e <= 2 {\n///         Vec::new()\n///     } else {\n///         vec![e / 2, e / 2 + 1]\n///     }\n/// });\n/// assert_eq!(par_iter.sum::<u32>(), 12);\n/// ```\npub fn walk_tree<S, B, I>(root: S, children_of: B) -> WalkTree<S, B>\nwhere\n    S: Send,\n    B: Fn(&S) -> I + Send + Sync,\n    I: IntoIterator<Item = S, IntoIter: DoubleEndedIterator>,\n{\n    let walker = WalkTreePostfix {\n        initial_state: root,\n        children_of,\n    };\n    WalkTree(walker)\n}\n\nimpl<S, B, I> ParallelIterator for WalkTree<S, B>\nwhere\n    S: Send,\n    B: Fn(&S) -> I + Send + Sync,\n    I: IntoIterator<Item = S, IntoIter: DoubleEndedIterator> + Send,\n{\n    type Item = S;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        self.0.drive_unindexed(consumer)\n    }\n}\n"
  },
  {
    "path": "src/iter/while_some.rs",
    "content": "use super::plumbing::*;\nuse super::*;\nuse std::sync::atomic::{AtomicBool, Ordering};\n\n/// `WhileSome` is an iterator that yields the `Some` elements of an iterator,\n/// halting as soon as any `None` is produced.\n///\n/// This struct is created by the [`while_some()`] method on [`ParallelIterator`]\n///\n/// [`while_some()`]: ParallelIterator::while_some()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\npub struct WhileSome<I> {\n    base: I,\n}\n\nimpl<I> WhileSome<I> {\n    /// Creates a new `WhileSome` iterator.\n    pub(super) fn new(base: I) -> Self {\n        WhileSome { base }\n    }\n}\n\nimpl<I, T> ParallelIterator for WhileSome<I>\nwhere\n    I: ParallelIterator<Item = Option<T>>,\n    T: Send,\n{\n    type Item = T;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let full = AtomicBool::new(false);\n        let consumer1 = WhileSomeConsumer {\n            base: consumer,\n            full: &full,\n        };\n        self.base.drive_unindexed(consumer1)\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n// Consumer implementation\n\nstruct WhileSomeConsumer<'f, C> {\n    base: C,\n    full: &'f AtomicBool,\n}\n\nimpl<'f, T, C> Consumer<Option<T>> for WhileSomeConsumer<'f, C>\nwhere\n    C: Consumer<T>,\n    T: Send,\n{\n    type Folder = WhileSomeFolder<'f, C::Folder>;\n    type Reducer = C::Reducer;\n    type Result = C::Result;\n\n    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {\n        let (left, right, reducer) = self.base.split_at(index);\n        (\n            WhileSomeConsumer { base: left, ..self },\n            WhileSomeConsumer {\n                base: right,\n                ..self\n            },\n            reducer,\n        )\n    }\n\n    fn into_folder(self) -> Self::Folder {\n        WhileSomeFolder {\n            base: self.base.into_folder(),\n            full: self.full,\n        }\n    }\n\n    fn full(&self) -> bool {\n        self.full.load(Ordering::Relaxed) || self.base.full()\n    }\n}\n\nimpl<'f, T, C> UnindexedConsumer<Option<T>> for WhileSomeConsumer<'f, C>\nwhere\n    C: UnindexedConsumer<T>,\n    T: Send,\n{\n    fn split_off_left(&self) -> Self {\n        WhileSomeConsumer {\n            base: self.base.split_off_left(),\n            ..*self\n        }\n    }\n\n    fn to_reducer(&self) -> Self::Reducer {\n        self.base.to_reducer()\n    }\n}\n\nstruct WhileSomeFolder<'f, C> {\n    base: C,\n    full: &'f AtomicBool,\n}\n\nimpl<'f, T, C> Folder<Option<T>> for WhileSomeFolder<'f, C>\nwhere\n    C: Folder<T>,\n{\n    type Result = C::Result;\n\n    fn consume(mut self, item: Option<T>) -> Self {\n        match item {\n            Some(item) => self.base = self.base.consume(item),\n            None => self.full.store(true, Ordering::Relaxed),\n        }\n        self\n    }\n\n    fn consume_iter<I>(mut self, iter: I) -> Self\n    where\n        I: IntoIterator<Item = Option<T>>,\n    {\n        fn some<T>(full: &AtomicBool) -> impl Fn(&Option<T>) -> bool + '_ {\n            move |x| match *x {\n                Some(_) => !full.load(Ordering::Relaxed),\n                None => {\n                    full.store(true, Ordering::Relaxed);\n                    false\n                }\n            }\n        }\n\n        self.base = self.base.consume_iter(\n            iter.into_iter()\n                .take_while(some(self.full))\n                .map(Option::unwrap),\n        );\n        self\n    }\n\n    fn complete(self) -> C::Result {\n        self.base.complete()\n    }\n\n    fn full(&self) -> bool {\n        self.full.load(Ordering::Relaxed) || self.base.full()\n    }\n}\n"
  },
  {
    "path": "src/iter/zip.rs",
    "content": "use super::plumbing::*;\nuse super::*;\nuse std::iter;\n\n/// `Zip` is an iterator that zips up `a` and `b` into a single iterator\n/// of pairs. This struct is created by the [`zip()`] method on\n/// [`IndexedParallelIterator`]\n///\n/// [`zip()`]: IndexedParallelIterator::zip()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\npub struct Zip<A, B> {\n    a: A,\n    b: B,\n}\n\nimpl<A, B> Zip<A, B> {\n    /// Creates a new `Zip` iterator.\n    pub(super) fn new(a: A, b: B) -> Self {\n        Zip { a, b }\n    }\n}\n\nimpl<A, B> ParallelIterator for Zip<A, B>\nwhere\n    A: IndexedParallelIterator,\n    B: IndexedParallelIterator,\n{\n    type Item = (A::Item, B::Item);\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<A, B> IndexedParallelIterator for Zip<A, B>\nwhere\n    A: IndexedParallelIterator,\n    B: IndexedParallelIterator,\n{\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        Ord::min(self.a.len(), self.b.len())\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        return self.a.with_producer(CallbackA {\n            callback,\n            b: self.b,\n        });\n\n        struct CallbackA<CB, B> {\n            callback: CB,\n            b: B,\n        }\n\n        impl<CB, ITEM, B> ProducerCallback<ITEM> for CallbackA<CB, B>\n        where\n            B: IndexedParallelIterator,\n            CB: ProducerCallback<(ITEM, B::Item)>,\n        {\n            type Output = CB::Output;\n\n            fn callback<A>(self, a_producer: A) -> Self::Output\n            where\n                A: Producer<Item = ITEM>,\n            {\n                self.b.with_producer(CallbackB {\n                    a_producer,\n                    callback: self.callback,\n                })\n            }\n        }\n\n        struct CallbackB<CB, A> {\n            a_producer: A,\n            callback: CB,\n        }\n\n        impl<CB, A, ITEM> ProducerCallback<ITEM> for CallbackB<CB, A>\n        where\n            A: Producer,\n            CB: ProducerCallback<(A::Item, ITEM)>,\n        {\n            type Output = CB::Output;\n\n            fn callback<B>(self, b_producer: B) -> Self::Output\n            where\n                B: Producer<Item = ITEM>,\n            {\n                self.callback.callback(ZipProducer {\n                    a: self.a_producer,\n                    b: b_producer,\n                })\n            }\n        }\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n\nstruct ZipProducer<A: Producer, B: Producer> {\n    a: A,\n    b: B,\n}\n\nimpl<A: Producer, B: Producer> Producer for ZipProducer<A, B> {\n    type Item = (A::Item, B::Item);\n    type IntoIter = iter::Zip<A::IntoIter, B::IntoIter>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.a.into_iter().zip(self.b.into_iter())\n    }\n\n    fn min_len(&self) -> usize {\n        Ord::max(self.a.min_len(), self.b.min_len())\n    }\n\n    fn max_len(&self) -> usize {\n        Ord::min(self.a.max_len(), self.b.max_len())\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let (a_left, a_right) = self.a.split_at(index);\n        let (b_left, b_right) = self.b.split_at(index);\n        (\n            ZipProducer {\n                a: a_left,\n                b: b_left,\n            },\n            ZipProducer {\n                a: a_right,\n                b: b_right,\n            },\n        )\n    }\n}\n"
  },
  {
    "path": "src/iter/zip_eq.rs",
    "content": "use super::plumbing::*;\nuse super::*;\n\n/// An [`IndexedParallelIterator`] that iterates over two parallel iterators of equal\n/// length simultaneously.\n///\n/// This struct is created by the [`zip_eq`] method on [`IndexedParallelIterator`],\n/// see its documentation for more information.\n///\n/// [`zip_eq`]: IndexedParallelIterator::zip_eq()\n#[must_use = \"iterator adaptors are lazy and do nothing unless consumed\"]\n#[derive(Debug, Clone)]\npub struct ZipEq<A, B> {\n    zip: Zip<A, B>,\n}\n\nimpl<A, B> ZipEq<A, B> {\n    /// Creates a new `ZipEq` iterator.\n    pub(super) fn new(a: A, b: B) -> Self {\n        ZipEq {\n            zip: super::Zip::new(a, b),\n        }\n    }\n}\n\nimpl<A, B> ParallelIterator for ZipEq<A, B>\nwhere\n    A: IndexedParallelIterator,\n    B: IndexedParallelIterator,\n{\n    type Item = (A::Item, B::Item);\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self.zip, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.zip.len())\n    }\n}\n\nimpl<A, B> IndexedParallelIterator for ZipEq<A, B>\nwhere\n    A: IndexedParallelIterator,\n    B: IndexedParallelIterator,\n{\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self.zip, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.zip.len()\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        self.zip.with_producer(callback)\n    }\n}\n"
  },
  {
    "path": "src/lib.rs",
    "content": "//! Rayon is a data-parallelism library that makes it easy to convert sequential\n//! computations into parallel.\n//!\n//! It is lightweight and convenient for introducing parallelism into existing\n//! code. It guarantees data-race free executions and takes advantage of\n//! parallelism when sensible, based on work-load at runtime.\n//!\n//! # How to use Rayon\n//!\n//! There are two ways to use Rayon:\n//!\n//! - **High-level parallel constructs** are the simplest way to use Rayon and also\n//!   typically the most efficient.\n//!   - [Parallel iterators] make it easy to convert a sequential iterator to\n//!     execute in parallel.\n//!     - The [`ParallelIterator`] trait defines general methods for all parallel iterators.\n//!     - The [`IndexedParallelIterator`] trait adds methods for iterators that support random\n//!       access.\n//!   - The [`par_sort`] method sorts `&mut [T]` slices (or vectors) in parallel.\n//!   - [`par_extend`] can be used to efficiently grow collections with items produced\n//!     by a parallel iterator.\n//! - **Custom tasks** let you divide your work into parallel tasks yourself.\n//!   - [`join`] is used to subdivide a task into two pieces.\n//!   - [`scope`] creates a scope within which you can create any number of parallel tasks.\n//!   - [`ThreadPoolBuilder`] can be used to create your own thread pools or customize\n//!     the global one.\n//!\n//! [Parallel iterators]: iter\n//! [`par_sort`]: slice::ParallelSliceMut::par_sort\n//! [`par_extend`]: iter::ParallelExtend::par_extend\n//! [`ParallelIterator`]: iter::ParallelIterator\n//! [`IndexedParallelIterator`]: iter::IndexedParallelIterator\n//!\n//! # Basic usage and the Rayon prelude\n//!\n//! First, you will need to add `rayon` to your `Cargo.toml`.\n//!\n//! Next, to use parallel iterators or the other high-level methods,\n//! you need to import several traits. Those traits are bundled into\n//! the module [`rayon::prelude`]. It is recommended that you import\n//! all of these traits at once by adding `use rayon::prelude::*` at\n//! the top of each module that uses Rayon methods.\n//!\n//! These traits give you access to the `par_iter` method which provides\n//! parallel implementations of many iterative functions such as [`map`],\n//! [`for_each`], [`filter`], [`fold`], and [more].\n//!\n//! [`rayon::prelude`]: prelude\n//! [`map`]: iter::ParallelIterator::map\n//! [`for_each`]: iter::ParallelIterator::for_each\n//! [`filter`]: iter::ParallelIterator::filter\n//! [`fold`]: iter::ParallelIterator::fold\n//! [more]: iter::ParallelIterator#provided-methods\n//!\n//! # Crate Layout\n//!\n//! Rayon extends many of the types found in the standard library with\n//! parallel iterator implementations. The modules in the `rayon`\n//! crate mirror [`std`] itself: so, e.g., the `option` module in\n//! Rayon contains parallel iterators for the `Option` type, which is\n//! found in [the `option` module of `std`]. Similarly, the\n//! `collections` module in Rayon offers parallel iterator types for\n//! [the `collections` from `std`]. You will rarely need to access\n//! these submodules unless you need to name iterator types\n//! explicitly.\n//!\n//! [the `option` module of `std`]: std::option\n//! [the `collections` from `std`]: std::collections\n//!\n//! # Targets without threading\n//!\n//! Rayon has limited support for targets without `std` threading implementations.\n//! See the [`rayon_core`] documentation for more information about its global fallback.\n//!\n//! # Other questions?\n//!\n//! See [the Rayon FAQ][faq].\n//!\n//! [faq]: https://github.com/rayon-rs/rayon/blob/main/FAQ.md\n\n#![deny(missing_debug_implementations)]\n#![deny(missing_docs)]\n#![deny(unreachable_pub)]\n#![warn(rust_2018_idioms)]\n\n#[macro_use]\nmod delegate;\n\n#[macro_use]\nmod private;\n\nmod split_producer;\n\npub mod array;\npub mod collections;\npub mod iter;\npub mod option;\npub mod prelude;\npub mod range;\npub mod range_inclusive;\npub mod result;\npub mod slice;\npub mod str;\npub mod string;\npub mod vec;\n\nmod math;\nmod par_either;\n\nmod compile_fail;\n\npub use rayon_core::FnContext;\npub use rayon_core::ThreadBuilder;\npub use rayon_core::ThreadPool;\npub use rayon_core::ThreadPoolBuildError;\npub use rayon_core::ThreadPoolBuilder;\npub use rayon_core::{broadcast, spawn_broadcast, BroadcastContext};\npub use rayon_core::{current_num_threads, current_thread_index, max_num_threads};\npub use rayon_core::{in_place_scope, scope, Scope};\npub use rayon_core::{in_place_scope_fifo, scope_fifo, ScopeFifo};\npub use rayon_core::{join, join_context};\npub use rayon_core::{spawn, spawn_fifo};\npub use rayon_core::{yield_local, yield_now, Yield};\n\n/// We need to transmit raw pointers across threads. It is possible to do this\n/// without any unsafe code by converting pointers to usize or to AtomicPtr<T>\n/// then back to a raw pointer for use. We prefer this approach because code\n/// that uses this type is more explicit.\n///\n/// Unsafe code is still required to dereference the pointer, so this type is\n/// not unsound on its own, although it does partly lift the unconditional\n/// !Send and !Sync on raw pointers. As always, dereference with care.\nstruct SendPtr<T>(*mut T);\n\n// SAFETY: !Send for raw pointers is not for safety, just as a lint\nunsafe impl<T: Send> Send for SendPtr<T> {}\n\n// SAFETY: !Sync for raw pointers is not for safety, just as a lint\nunsafe impl<T: Send> Sync for SendPtr<T> {}\n\nimpl<T> SendPtr<T> {\n    // Helper to avoid disjoint captures of `send_ptr.0`\n    fn get(self) -> *mut T {\n        self.0\n    }\n}\n\n// Implement Clone without the T: Clone bound from the derive\nimpl<T> Clone for SendPtr<T> {\n    fn clone(&self) -> Self {\n        *self\n    }\n}\n\n// Implement Copy without the T: Copy bound from the derive\nimpl<T> Copy for SendPtr<T> {}\n"
  },
  {
    "path": "src/math.rs",
    "content": "use std::ops::{Bound, Range, RangeBounds};\n\n/// Normalize arbitrary `RangeBounds` to a `Range`\npub(super) fn simplify_range(range: impl RangeBounds<usize>, len: usize) -> Range<usize> {\n    let start = match range.start_bound() {\n        Bound::Unbounded => 0,\n        Bound::Included(&i) if i <= len => i,\n        Bound::Excluded(&i) if i < len => i + 1,\n        bound => panic!(\"range start {bound:?} should be <= length {len}\"),\n    };\n    let end = match range.end_bound() {\n        Bound::Unbounded => len,\n        Bound::Excluded(&i) if i <= len => i,\n        Bound::Included(&i) if i < len => i + 1,\n        bound => panic!(\"range end {bound:?} should be <= length {len}\"),\n    };\n    if start > end {\n        panic!(\n            \"range start {:?} should be <= range end {:?}\",\n            range.start_bound(),\n            range.end_bound()\n        );\n    }\n    start..end\n}\n"
  },
  {
    "path": "src/option.rs",
    "content": "//! Parallel iterator types for [options]\n//!\n//! You will rarely need to interact with this module directly unless you need\n//! to name one of the iterator types.\n//!\n//! [options]: std::option\n\nuse crate::iter::plumbing::*;\nuse crate::iter::*;\nuse std::sync::atomic::{AtomicBool, Ordering};\n\n/// A parallel iterator over the value in [`Some`] variant of an [`Option`].\n///\n/// The iterator yields one value if the [`Option`] is a [`Some`], otherwise none.\n///\n/// This `struct` is created by the [`into_par_iter`] function.\n///\n/// [`into_par_iter`]: IntoParallelIterator::into_par_iter()\n#[derive(Debug, Clone)]\npub struct IntoIter<T> {\n    opt: Option<T>,\n}\n\nimpl<T: Send> IntoParallelIterator for Option<T> {\n    type Item = T;\n    type Iter = IntoIter<T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        IntoIter { opt: self }\n    }\n}\n\nimpl<T: Send> ParallelIterator for IntoIter<T> {\n    type Item = T;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        self.drive(consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<T: Send> IndexedParallelIterator for IntoIter<T> {\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        let mut folder = consumer.into_folder();\n        if let Some(item) = self.opt {\n            folder = folder.consume(item);\n        }\n        folder.complete()\n    }\n\n    fn len(&self) -> usize {\n        match self.opt {\n            Some(_) => 1,\n            None => 0,\n        }\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        callback.callback(OptionProducer { opt: self.opt })\n    }\n}\n\n/// A parallel iterator over a reference to the [`Some`] variant of an [`Option`].\n///\n/// The iterator yields one value if the [`Option`] is a [`Some`], otherwise none.\n///\n/// This `struct` is created by the [`par_iter`] function.\n///\n/// [`par_iter`]: IntoParallelRefIterator::par_iter()\n#[derive(Debug)]\npub struct Iter<'a, T> {\n    inner: IntoIter<&'a T>,\n}\n\nimpl<T> Clone for Iter<'_, T> {\n    fn clone(&self) -> Self {\n        Iter {\n            inner: self.inner.clone(),\n        }\n    }\n}\n\nimpl<'a, T: Sync> IntoParallelIterator for &'a Option<T> {\n    type Item = &'a T;\n    type Iter = Iter<'a, T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        Iter {\n            inner: self.as_ref().into_par_iter(),\n        }\n    }\n}\n\ndelegate_indexed_iterator! {\n    Iter<'a, T> => &'a T,\n    impl<'a, T: Sync>\n}\n\n/// A parallel iterator over a mutable reference to the [`Some`] variant of an [`Option`].\n///\n/// The iterator yields one value if the [`Option`] is a [`Some`], otherwise none.\n///\n/// This `struct` is created by the [`par_iter_mut`] function.\n///\n/// [`par_iter_mut`]: IntoParallelRefMutIterator::par_iter_mut()\n#[derive(Debug)]\npub struct IterMut<'a, T> {\n    inner: IntoIter<&'a mut T>,\n}\n\nimpl<'a, T: Send> IntoParallelIterator for &'a mut Option<T> {\n    type Item = &'a mut T;\n    type Iter = IterMut<'a, T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        IterMut {\n            inner: self.as_mut().into_par_iter(),\n        }\n    }\n}\n\ndelegate_indexed_iterator! {\n    IterMut<'a, T> => &'a mut T,\n    impl<'a, T: Send>\n}\n\n/// Private producer for an option\nstruct OptionProducer<T: Send> {\n    opt: Option<T>,\n}\n\nimpl<T: Send> Producer for OptionProducer<T> {\n    type Item = T;\n    type IntoIter = std::option::IntoIter<T>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.opt.into_iter()\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        debug_assert!(index <= 1);\n        let none = OptionProducer { opt: None };\n        if index == 0 {\n            (none, self)\n        } else {\n            (self, none)\n        }\n    }\n}\n\n/// Collect an arbitrary `Option`-wrapped collection.\n///\n/// If any item is `None`, then all previous items collected are discarded,\n/// and it returns only `None`.\nimpl<C, T> FromParallelIterator<Option<T>> for Option<C>\nwhere\n    C: FromParallelIterator<T>,\n    T: Send,\n{\n    fn from_par_iter<I>(par_iter: I) -> Self\n    where\n        I: IntoParallelIterator<Item = Option<T>>,\n    {\n        fn check<T>(found_none: &AtomicBool) -> impl Fn(&Option<T>) + '_ {\n            move |item| {\n                if item.is_none() {\n                    found_none.store(true, Ordering::Relaxed);\n                }\n            }\n        }\n\n        let found_none = AtomicBool::new(false);\n        let collection = par_iter\n            .into_par_iter()\n            .inspect(check(&found_none))\n            .while_some()\n            .collect();\n\n        if found_none.load(Ordering::Relaxed) {\n            None\n        } else {\n            Some(collection)\n        }\n    }\n}\n"
  },
  {
    "path": "src/par_either.rs",
    "content": "use crate::iter::plumbing::*;\nuse crate::iter::Either::{Left, Right};\nuse crate::iter::*;\n\n/// `Either<L, R>` is a parallel iterator if both `L` and `R` are parallel iterators.\nimpl<L, R> ParallelIterator for Either<L, R>\nwhere\n    L: ParallelIterator,\n    R: ParallelIterator<Item = L::Item>,\n{\n    type Item = L::Item;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        match self {\n            Left(iter) => iter.drive_unindexed(consumer),\n            Right(iter) => iter.drive_unindexed(consumer),\n        }\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        self.as_ref().either(L::opt_len, R::opt_len)\n    }\n}\n\nimpl<L, R> IndexedParallelIterator for Either<L, R>\nwhere\n    L: IndexedParallelIterator,\n    R: IndexedParallelIterator<Item = L::Item>,\n{\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        match self {\n            Left(iter) => iter.drive(consumer),\n            Right(iter) => iter.drive(consumer),\n        }\n    }\n\n    fn len(&self) -> usize {\n        self.as_ref().either(L::len, R::len)\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        match self {\n            Left(iter) => iter.with_producer(callback),\n            Right(iter) => iter.with_producer(callback),\n        }\n    }\n}\n\n/// `Either<L, R>` can be extended if both `L` and `R` are parallel extendable.\nimpl<L, R, T> ParallelExtend<T> for Either<L, R>\nwhere\n    L: ParallelExtend<T>,\n    R: ParallelExtend<T>,\n    T: Send,\n{\n    fn par_extend<I>(&mut self, par_iter: I)\n    where\n        I: IntoParallelIterator<Item = T>,\n    {\n        match self.as_mut() {\n            Left(collection) => collection.par_extend(par_iter),\n            Right(collection) => collection.par_extend(par_iter),\n        }\n    }\n}\n"
  },
  {
    "path": "src/prelude.rs",
    "content": "//! The rayon prelude imports the various `ParallelIterator` traits.\n//! The intention is that one can include `use rayon::prelude::*` and\n//! have easy access to the various traits and methods you will need.\n\npub use crate::iter::FromParallelIterator;\npub use crate::iter::IndexedParallelIterator;\npub use crate::iter::IntoParallelIterator;\npub use crate::iter::IntoParallelRefIterator;\npub use crate::iter::IntoParallelRefMutIterator;\npub use crate::iter::ParallelBridge;\npub use crate::iter::ParallelDrainFull;\npub use crate::iter::ParallelDrainRange;\npub use crate::iter::ParallelExtend;\npub use crate::iter::ParallelIterator;\npub use crate::slice::ParallelSlice;\npub use crate::slice::ParallelSliceMut;\npub use crate::str::ParallelString;\n"
  },
  {
    "path": "src/private.rs",
    "content": "//! The public parts of this private module are used to create traits\n//! that cannot be implemented outside of our own crate.  This way we\n//! can feel free to extend those traits without worrying about it\n//! being a breaking change for other implementations.\n\n/// If this type is pub but not publicly reachable, third parties\n/// can't name it and can't implement traits using it.\n#[allow(missing_debug_implementations)]\npub struct PrivateMarker;\n\nmacro_rules! private_decl {\n    () => {\n        /// This trait is private; this method exists to make it\n        /// impossible to implement outside the crate.\n        #[doc(hidden)]\n        fn __rayon_private__(&self) -> crate::private::PrivateMarker;\n    };\n}\n\nmacro_rules! private_impl {\n    () => {\n        fn __rayon_private__(&self) -> crate::private::PrivateMarker {\n            crate::private::PrivateMarker\n        }\n    };\n}\n"
  },
  {
    "path": "src/range.rs",
    "content": "//! Parallel iterator types for [ranges],\n//! the type for values created by `a..b` expressions\n//!\n//! You will rarely need to interact with this module directly unless you have\n//! need to name one of the iterator types.\n//!\n//! ```\n//! use rayon::prelude::*;\n//!\n//! let r = (0..100u64).into_par_iter()\n//!                    .sum();\n//!\n//! // compare result with sequential calculation\n//! assert_eq!((0..100).sum::<u64>(), r);\n//! ```\n//!\n//! [ranges]: std::ops::Range\n\nuse crate::iter::plumbing::*;\nuse crate::iter::*;\nuse std::ops::Range;\n\n/// Parallel iterator over a range, implemented for all integer types and `char`.\n///\n/// **Note:** The `zip` operation requires `IndexedParallelIterator`\n/// which is not implemented for `u64`, `i64`, `u128`, or `i128`.\n///\n/// ```\n/// use rayon::prelude::*;\n///\n/// let p = (0..25usize).into_par_iter()\n///                   .zip(0..25usize)\n///                   .filter(|&(x, y)| x % 5 == 0 || y % 5 == 0)\n///                   .map(|(x, y)| x * y)\n///                   .sum::<usize>();\n///\n/// let s = (0..25usize).zip(0..25)\n///                   .filter(|&(x, y)| x % 5 == 0 || y % 5 == 0)\n///                   .map(|(x, y)| x * y)\n///                   .sum();\n///\n/// assert_eq!(p, s);\n/// ```\n#[derive(Debug, Clone)]\npub struct Iter<T> {\n    range: Range<T>,\n}\n\n/// Implemented for ranges of all primitive integer types and `char`.\nimpl<T> IntoParallelIterator for Range<T>\nwhere\n    Iter<T>: ParallelIterator,\n{\n    type Item = <Iter<T> as ParallelIterator>::Item;\n    type Iter = Iter<T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        Iter { range: self }\n    }\n}\n\nstruct IterProducer<T> {\n    range: Range<T>,\n}\n\nimpl<T> IntoIterator for IterProducer<T>\nwhere\n    Range<T>: Iterator,\n{\n    type Item = <Range<T> as Iterator>::Item;\n    type IntoIter = Range<T>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.range\n    }\n}\n\n/// These traits help drive integer type inference. Without them, an unknown `{integer}` type only\n/// has constraints on `Iter<{integer}>`, which will probably give up and use `i32`. By adding\n/// these traits on the item type, the compiler can see a more direct constraint to infer like\n/// `{integer}: RangeInteger`, which works better. See `test_issue_833` for an example.\n///\n/// They have to be `pub` since they're seen in the public `impl ParallelIterator` constraints, but\n/// we put them in a private modules so they're not actually reachable in our public API.\nmod private {\n    use super::*;\n\n    /// Implementation details of `ParallelIterator for Iter<Self>`\n    pub trait RangeInteger: Sized + Send {\n        private_decl! {}\n\n        fn drive_unindexed<C>(iter: Iter<Self>, consumer: C) -> C::Result\n        where\n            C: UnindexedConsumer<Self>;\n\n        fn opt_len(iter: &Iter<Self>) -> Option<usize>;\n    }\n\n    /// Implementation details of `IndexedParallelIterator for Iter<Self>`\n    pub trait IndexedRangeInteger: RangeInteger {\n        private_decl! {}\n\n        fn drive<C>(iter: Iter<Self>, consumer: C) -> C::Result\n        where\n            C: Consumer<Self>;\n\n        fn len(iter: &Iter<Self>) -> usize;\n\n        fn with_producer<CB>(iter: Iter<Self>, callback: CB) -> CB::Output\n        where\n            CB: ProducerCallback<Self>;\n    }\n}\nuse private::{IndexedRangeInteger, RangeInteger};\n\nimpl<T: RangeInteger> ParallelIterator for Iter<T> {\n    type Item = T;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<T>,\n    {\n        T::drive_unindexed(self, consumer)\n    }\n\n    #[inline]\n    fn opt_len(&self) -> Option<usize> {\n        T::opt_len(self)\n    }\n}\n\nimpl<T: IndexedRangeInteger> IndexedParallelIterator for Iter<T> {\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<T>,\n    {\n        T::drive(self, consumer)\n    }\n\n    #[inline]\n    fn len(&self) -> usize {\n        T::len(self)\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<T>,\n    {\n        T::with_producer(self, callback)\n    }\n}\n\nmacro_rules! indexed_range_impl {\n    ( $t:ty ) => {\n        impl RangeInteger for $t {\n            private_impl! {}\n\n            fn drive_unindexed<C>(iter: Iter<$t>, consumer: C) -> C::Result\n            where\n                C: UnindexedConsumer<$t>,\n            {\n                bridge(iter, consumer)\n            }\n\n            fn opt_len(iter: &Iter<$t>) -> Option<usize> {\n                Some(iter.range.len())\n            }\n        }\n\n        impl IndexedRangeInteger for $t {\n            private_impl! {}\n\n            fn drive<C>(iter: Iter<$t>, consumer: C) -> C::Result\n            where\n                C: Consumer<$t>,\n            {\n                bridge(iter, consumer)\n            }\n\n            fn len(iter: &Iter<$t>) -> usize {\n                iter.range.len()\n            }\n\n            fn with_producer<CB>(iter: Iter<$t>, callback: CB) -> CB::Output\n            where\n                CB: ProducerCallback<$t>,\n            {\n                callback.callback(IterProducer { range: iter.range })\n            }\n        }\n\n        impl Producer for IterProducer<$t> {\n            type Item = <Range<$t> as Iterator>::Item;\n            type IntoIter = Range<$t>;\n            fn into_iter(self) -> Self::IntoIter {\n                self.range\n            }\n\n            fn split_at(self, index: usize) -> (Self, Self) {\n                assert!(index <= self.range.len());\n                // For signed $t, the length and requested index could be greater than $t::MAX, and\n                // then `index as $t` could wrap to negative, so wrapping_add is necessary.\n                let mid = self.range.start.wrapping_add(index as $t);\n                let left = self.range.start..mid;\n                let right = mid..self.range.end;\n                (IterProducer { range: left }, IterProducer { range: right })\n            }\n        }\n    };\n}\n\ntrait UnindexedRangeLen<L> {\n    fn unindexed_len(&self) -> L;\n}\n\nmacro_rules! unindexed_range_impl {\n    ( $t:ty, $len_t:ty ) => {\n        impl UnindexedRangeLen<$len_t> for Range<$t> {\n            fn unindexed_len(&self) -> $len_t {\n                let &Range { start, end } = self;\n                if end > start {\n                    end.wrapping_sub(start) as $len_t\n                } else {\n                    0\n                }\n            }\n        }\n\n        impl RangeInteger for $t {\n            private_impl! {}\n\n            fn drive_unindexed<C>(iter: Iter<$t>, consumer: C) -> C::Result\n            where\n                C: UnindexedConsumer<$t>,\n            {\n                #[inline]\n                fn offset(start: $t) -> impl Fn(usize) -> $t {\n                    move |i| start.wrapping_add(i as $t)\n                }\n\n                if let Some(len) = iter.opt_len() {\n                    // Drive this in indexed mode for better `collect`.\n                    (0..len)\n                        .into_par_iter()\n                        .map(offset(iter.range.start))\n                        .drive(consumer)\n                } else {\n                    bridge_unindexed(IterProducer { range: iter.range }, consumer)\n                }\n            }\n\n            fn opt_len(iter: &Iter<$t>) -> Option<usize> {\n                usize::try_from(iter.range.unindexed_len()).ok()\n            }\n        }\n\n        impl UnindexedProducer for IterProducer<$t> {\n            type Item = $t;\n\n            fn split(mut self) -> (Self, Option<Self>) {\n                let index = self.range.unindexed_len() / 2;\n                if index > 0 {\n                    let mid = self.range.start.wrapping_add(index as $t);\n                    let right = mid..self.range.end;\n                    self.range.end = mid;\n                    (self, Some(IterProducer { range: right }))\n                } else {\n                    (self, None)\n                }\n            }\n\n            fn fold_with<F>(self, folder: F) -> F\n            where\n                F: Folder<Self::Item>,\n            {\n                folder.consume_iter(self)\n            }\n        }\n    };\n}\n\n// all Range<T> with ExactSizeIterator\nindexed_range_impl! {u8}\nindexed_range_impl! {u16}\nindexed_range_impl! {u32}\nindexed_range_impl! {usize}\nindexed_range_impl! {i8}\nindexed_range_impl! {i16}\nindexed_range_impl! {i32}\nindexed_range_impl! {isize}\n\n// other Range<T> with just Iterator\nunindexed_range_impl! {u64, u64}\nunindexed_range_impl! {i64, u64}\nunindexed_range_impl! {u128, u128}\nunindexed_range_impl! {i128, u128}\n\n// char is special because of the surrogate range hole\nmacro_rules! convert_char {\n    ( $self:ident . $method:ident ( $( $arg:expr ),* ) ) => {{\n        let start = $self.range.start as u32;\n        let end = $self.range.end as u32;\n        if start < 0xD800 && 0xE000 < end {\n            // chain the before and after surrogate range fragments\n            (start..0xD800)\n                .into_par_iter()\n                .chain(0xE000..end)\n                .map(|codepoint| unsafe { char::from_u32_unchecked(codepoint) })\n                .$method($( $arg ),*)\n        } else {\n            // no surrogate range to worry about\n            (start..end)\n                .into_par_iter()\n                .map(|codepoint| unsafe { char::from_u32_unchecked(codepoint) })\n                .$method($( $arg ),*)\n        }\n    }};\n}\n\nimpl ParallelIterator for Iter<char> {\n    type Item = char;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        convert_char!(self.drive(consumer))\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl IndexedParallelIterator for Iter<char> {\n    // Split at the surrogate range first if we're allowed to\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        convert_char!(self.drive(consumer))\n    }\n\n    fn len(&self) -> usize {\n        // Taken from <char as Step>::steps_between\n        let start = self.range.start as u32;\n        let end = self.range.end as u32;\n        if start < end {\n            let mut count = end - start;\n            if start < 0xD800 && 0xE000 <= end {\n                count -= 0x800\n            }\n            count as usize\n        } else {\n            0\n        }\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        convert_char!(self.with_producer(callback))\n    }\n}\n\n#[test]\nfn check_range_split_at_overflow() {\n    // Note, this split index overflows i8!\n    let producer = IterProducer { range: -100i8..100 };\n    let (left, right) = producer.split_at(150);\n    let r1: i32 = left.range.map(i32::from).sum();\n    let r2: i32 = right.range.map(i32::from).sum();\n    assert_eq!(r1 + r2, -100);\n}\n\n#[test]\nfn test_i128_len_doesnt_overflow() {\n    // Using parse because some versions of rust don't allow long literals\n    let octillion: i128 = \"1000000000000000000000000000\".parse().unwrap();\n    let producer = IterProducer {\n        range: 0..octillion,\n    };\n\n    assert_eq!(octillion as u128, producer.range.unindexed_len());\n    assert_eq!(octillion as u128, (0..octillion).unindexed_len());\n    assert_eq!(\n        2 * octillion as u128,\n        (-octillion..octillion).unindexed_len()\n    );\n\n    assert_eq!(u128::MAX, (i128::MIN..i128::MAX).unindexed_len());\n}\n\n#[test]\nfn test_u64_opt_len() {\n    assert_eq!(Some(100), (0..100u64).into_par_iter().opt_len());\n    assert_eq!(\n        Some(usize::MAX),\n        (0..usize::MAX as u64).into_par_iter().opt_len()\n    );\n    if (usize::MAX as u64) < u64::MAX {\n        assert_eq!(\n            None,\n            (0..(usize::MAX as u64).wrapping_add(1))\n                .into_par_iter()\n                .opt_len()\n        );\n        assert_eq!(None, (0..u64::MAX).into_par_iter().opt_len());\n    }\n}\n\n#[test]\nfn test_u128_opt_len() {\n    assert_eq!(Some(100), (0..100u128).into_par_iter().opt_len());\n    assert_eq!(\n        Some(usize::MAX),\n        (0..usize::MAX as u128).into_par_iter().opt_len()\n    );\n    assert_eq!(None, (0..1 + usize::MAX as u128).into_par_iter().opt_len());\n    assert_eq!(None, (0..u128::MAX).into_par_iter().opt_len());\n}\n\n// `usize as i64` can overflow, so make sure to wrap it appropriately\n// when using the `opt_len` \"indexed\" mode.\n#[test]\n#[cfg(target_pointer_width = \"64\")]\nfn test_usize_i64_overflow() {\n    use crate::ThreadPoolBuilder;\n\n    let iter = (-2..i64::MAX).into_par_iter();\n    assert_eq!(iter.opt_len(), Some(i64::MAX as usize + 2));\n\n    // always run with multiple threads to split into, or this will take forever...\n    let pool = ThreadPoolBuilder::new().num_threads(8).build().unwrap();\n    pool.install(|| assert_eq!(iter.find_last(|_| true), Some(i64::MAX - 1)));\n}\n\n#[test]\nfn test_issue_833() {\n    fn is_even(n: i64) -> bool {\n        n % 2 == 0\n    }\n\n    // The integer type should be inferred from `is_even`\n    let v: Vec<_> = (1..100).into_par_iter().filter(|&x| is_even(x)).collect();\n    assert!(v.into_iter().eq((2..100).step_by(2)));\n\n    // Try examples with indexed iterators too\n    let pos = (0..100).into_par_iter().position_any(|x| x == 50i16);\n    assert_eq!(pos, Some(50usize));\n\n    assert!((0..100)\n        .into_par_iter()\n        .zip(0..100)\n        .all(|(a, b)| i16::eq(&a, &b)));\n}\n"
  },
  {
    "path": "src/range_inclusive.rs",
    "content": "//! Parallel iterator types for [inclusive ranges],\n//! the type for values created by `a..=b` expressions\n//!\n//! You will rarely need to interact with this module directly unless you have\n//! need to name one of the iterator types.\n//!\n//! ```\n//! use rayon::prelude::*;\n//!\n//! let r = (0..=100u64).into_par_iter()\n//!                     .sum();\n//!\n//! // compare result with sequential calculation\n//! assert_eq!((0..=100).sum::<u64>(), r);\n//! ```\n//!\n//! [inclusive ranges]: std::ops::RangeInclusive\n\nuse crate::iter::plumbing::*;\nuse crate::iter::*;\nuse std::ops::RangeInclusive;\n\n/// Parallel iterator over an inclusive range, implemented for all integer types and `char`.\n///\n/// **Note:** The `zip` operation requires `IndexedParallelIterator`\n/// which is only implemented for `u8`, `i8`, `u16`, `i16`, and `char`.\n///\n/// ```\n/// use rayon::prelude::*;\n///\n/// let p = (0..=25u16).into_par_iter()\n///                   .zip(0..=25u16)\n///                   .filter(|&(x, y)| x % 5 == 0 || y % 5 == 0)\n///                   .map(|(x, y)| x * y)\n///                   .sum::<u16>();\n///\n/// let s = (0..=25u16).zip(0..=25u16)\n///                   .filter(|&(x, y)| x % 5 == 0 || y % 5 == 0)\n///                   .map(|(x, y)| x * y)\n///                   .sum();\n///\n/// assert_eq!(p, s);\n/// ```\n#[derive(Debug, Clone)]\npub struct Iter<T> {\n    range: RangeInclusive<T>,\n}\n\nimpl<T> Iter<T>\nwhere\n    RangeInclusive<T>: Eq,\n    T: Ord + Copy,\n{\n    /// Returns `Some((start, end))` for `start..=end`, or `None` if it is exhausted.\n    ///\n    /// Note that `RangeInclusive` does not specify the bounds of an exhausted iterator,\n    /// so this is a way for us to figure out what we've got.  Thankfully, all of the\n    /// integer types we care about can be trivially cloned.\n    fn bounds(&self) -> Option<(T, T)> {\n        let start = *self.range.start();\n        let end = *self.range.end();\n        if start <= end && self.range == (start..=end) {\n            // If the range is still nonempty, this is obviously true\n            // If the range is exhausted, either start > end or\n            // the range does not equal start..=end.\n            Some((start, end))\n        } else {\n            None\n        }\n    }\n}\n\n/// Implemented for ranges of all primitive integer types and `char`.\nimpl<T> IntoParallelIterator for RangeInclusive<T>\nwhere\n    Iter<T>: ParallelIterator,\n{\n    type Item = <Iter<T> as ParallelIterator>::Item;\n    type Iter = Iter<T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        Iter { range: self }\n    }\n}\n\n/// These traits help drive integer type inference. Without them, an unknown `{integer}` type only\n/// has constraints on `Iter<{integer}>`, which will probably give up and use `i32`. By adding\n/// these traits on the item type, the compiler can see a more direct constraint to infer like\n/// `{integer}: RangeInteger`, which works better. See `test_issue_833` for an example.\n///\n/// They have to be `pub` since they're seen in the public `impl ParallelIterator` constraints, but\n/// we put them in a private modules so they're not actually reachable in our public API.\nmod private {\n    use super::*;\n\n    /// Implementation details of `ParallelIterator for Iter<Self>`\n    pub trait RangeInteger: Sized + Send {\n        private_decl! {}\n\n        fn drive_unindexed<C>(iter: Iter<Self>, consumer: C) -> C::Result\n        where\n            C: UnindexedConsumer<Self>;\n\n        fn opt_len(iter: &Iter<Self>) -> Option<usize>;\n    }\n\n    /// Implementation details of `IndexedParallelIterator for Iter<Self>`\n    pub trait IndexedRangeInteger: RangeInteger {\n        private_decl! {}\n\n        fn drive<C>(iter: Iter<Self>, consumer: C) -> C::Result\n        where\n            C: Consumer<Self>;\n\n        fn len(iter: &Iter<Self>) -> usize;\n\n        fn with_producer<CB>(iter: Iter<Self>, callback: CB) -> CB::Output\n        where\n            CB: ProducerCallback<Self>;\n    }\n}\nuse private::{IndexedRangeInteger, RangeInteger};\n\nimpl<T: RangeInteger> ParallelIterator for Iter<T> {\n    type Item = T;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<T>,\n    {\n        T::drive_unindexed(self, consumer)\n    }\n\n    #[inline]\n    fn opt_len(&self) -> Option<usize> {\n        T::opt_len(self)\n    }\n}\n\nimpl<T: IndexedRangeInteger> IndexedParallelIterator for Iter<T> {\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<T>,\n    {\n        T::drive(self, consumer)\n    }\n\n    #[inline]\n    fn len(&self) -> usize {\n        T::len(self)\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<T>,\n    {\n        T::with_producer(self, callback)\n    }\n}\n\nmacro_rules! convert {\n    ( $iter:ident . $method:ident ( $( $arg:expr ),* ) ) => {\n        if let Some((start, end)) = $iter.bounds() {\n            if let Some(end) = end.checked_add(1) {\n                (start..end).into_par_iter().$method($( $arg ),*)\n            } else {\n                (start..end).into_par_iter().chain(once(end)).$method($( $arg ),*)\n            }\n        } else {\n            empty::<Self>().$method($( $arg ),*)\n        }\n    };\n}\n\nmacro_rules! parallel_range_impl {\n    ( $t:ty ) => {\n        impl RangeInteger for $t {\n            private_impl! {}\n\n            fn drive_unindexed<C>(iter: Iter<$t>, consumer: C) -> C::Result\n            where\n                C: UnindexedConsumer<$t>,\n            {\n                convert!(iter.drive_unindexed(consumer))\n            }\n\n            fn opt_len(iter: &Iter<$t>) -> Option<usize> {\n                convert!(iter.opt_len())\n            }\n        }\n    };\n}\n\nmacro_rules! indexed_range_impl {\n    ( $t:ty ) => {\n        parallel_range_impl! { $t }\n\n        impl IndexedRangeInteger for $t {\n            private_impl! {}\n\n            fn drive<C>(iter: Iter<$t>, consumer: C) -> C::Result\n            where\n                C: Consumer<$t>,\n            {\n                convert!(iter.drive(consumer))\n            }\n\n            fn len(iter: &Iter<$t>) -> usize {\n                iter.range.len()\n            }\n\n            fn with_producer<CB>(iter: Iter<$t>, callback: CB) -> CB::Output\n            where\n                CB: ProducerCallback<$t>,\n            {\n                convert!(iter.with_producer(callback))\n            }\n        }\n    };\n}\n\n// all RangeInclusive<T> with ExactSizeIterator\nindexed_range_impl! {u8}\nindexed_range_impl! {u16}\nindexed_range_impl! {i8}\nindexed_range_impl! {i16}\n\n// other RangeInclusive<T> with just Iterator\nparallel_range_impl! {usize}\nparallel_range_impl! {isize}\nparallel_range_impl! {u32}\nparallel_range_impl! {i32}\nparallel_range_impl! {u64}\nparallel_range_impl! {i64}\nparallel_range_impl! {u128}\nparallel_range_impl! {i128}\n\n// char is special\nmacro_rules! convert_char {\n    ( $self:ident . $method:ident ( $( $arg:expr ),* ) ) => {\n        if let Some((start, end)) = $self.bounds() {\n            let start = start as u32;\n            let end = end as u32;\n            if start < 0xD800 && 0xE000 <= end {\n                // chain the before and after surrogate range fragments\n                (start..0xD800)\n                    .into_par_iter()\n                    .chain(0xE000..end + 1) // cannot use RangeInclusive, so add one to end\n                    .map(|codepoint| unsafe { char::from_u32_unchecked(codepoint) })\n                    .$method($( $arg ),*)\n            } else {\n                // no surrogate range to worry about\n                (start..end + 1) // cannot use RangeInclusive, so add one to end\n                    .into_par_iter()\n                    .map(|codepoint| unsafe { char::from_u32_unchecked(codepoint) })\n                    .$method($( $arg ),*)\n            }\n        } else {\n            empty::<char>().$method($( $arg ),*)\n        }\n    };\n}\n\nimpl ParallelIterator for Iter<char> {\n    type Item = char;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        convert_char!(self.drive(consumer))\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\n// Range<u32> is broken on 16 bit platforms, may as well benefit from it\nimpl IndexedParallelIterator for Iter<char> {\n    // Split at the surrogate range first if we're allowed to\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        convert_char!(self.drive(consumer))\n    }\n\n    fn len(&self) -> usize {\n        if let Some((start, end)) = self.bounds() {\n            // Taken from <char as Step>::steps_between\n            let start = start as u32;\n            let end = end as u32;\n            let mut count = end - start;\n            if start < 0xD800 && 0xE000 <= end {\n                count -= 0x800\n            }\n            (count + 1) as usize // add one for inclusive\n        } else {\n            0\n        }\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        convert_char!(self.with_producer(callback))\n    }\n}\n\n#[test]\n#[cfg(target_pointer_width = \"64\")]\nfn test_u32_opt_len() {\n    assert_eq!(Some(101), (0..=100u32).into_par_iter().opt_len());\n    assert_eq!(\n        Some(u32::MAX as usize),\n        (0..=u32::MAX - 1).into_par_iter().opt_len()\n    );\n    assert_eq!(\n        Some(u32::MAX as usize + 1),\n        (0..=u32::MAX).into_par_iter().opt_len()\n    );\n}\n\n#[test]\nfn test_u64_opt_len() {\n    assert_eq!(Some(101), (0..=100u64).into_par_iter().opt_len());\n    assert_eq!(\n        Some(usize::MAX),\n        (0..=usize::MAX as u64 - 1).into_par_iter().opt_len()\n    );\n    assert_eq!(None, (0..=usize::MAX as u64).into_par_iter().opt_len());\n    assert_eq!(None, (0..=u64::MAX).into_par_iter().opt_len());\n}\n\n#[test]\nfn test_u128_opt_len() {\n    assert_eq!(Some(101), (0..=100u128).into_par_iter().opt_len());\n    assert_eq!(\n        Some(usize::MAX),\n        (0..=usize::MAX as u128 - 1).into_par_iter().opt_len()\n    );\n    assert_eq!(None, (0..=usize::MAX as u128).into_par_iter().opt_len());\n    assert_eq!(None, (0..=u128::MAX).into_par_iter().opt_len());\n}\n\n// `usize as i64` can overflow, so make sure to wrap it appropriately\n// when using the `opt_len` \"indexed\" mode.\n#[test]\n#[cfg(target_pointer_width = \"64\")]\nfn test_usize_i64_overflow() {\n    use crate::ThreadPoolBuilder;\n\n    let iter = (-2..=i64::MAX).into_par_iter();\n    assert_eq!(iter.opt_len(), Some(i64::MAX as usize + 3));\n\n    // always run with multiple threads to split into, or this will take forever...\n    let pool = ThreadPoolBuilder::new().num_threads(8).build().unwrap();\n    pool.install(|| assert_eq!(iter.find_last(|_| true), Some(i64::MAX)));\n}\n\n#[test]\nfn test_issue_833() {\n    fn is_even(n: i64) -> bool {\n        n % 2 == 0\n    }\n\n    // The integer type should be inferred from `is_even`\n    let v: Vec<_> = (1..=100).into_par_iter().filter(|&x| is_even(x)).collect();\n    assert!(v.into_iter().eq((2..=100).step_by(2)));\n\n    // Try examples with indexed iterators too\n    let pos = (0..=100).into_par_iter().position_any(|x| x == 50i16);\n    assert_eq!(pos, Some(50usize));\n\n    assert!((0..=100)\n        .into_par_iter()\n        .zip(0..=100)\n        .all(|(a, b)| i16::eq(&a, &b)));\n}\n"
  },
  {
    "path": "src/result.rs",
    "content": "//! Parallel iterator types for [results]\n//!\n//! You will rarely need to interact with this module directly unless you need\n//! to name one of the iterator types.\n//!\n//! [results]: std::result\n\nuse crate::iter::plumbing::*;\nuse crate::iter::*;\nuse std::sync::Mutex;\n\nuse crate::option;\n\n/// Parallel iterator over a result\n#[derive(Debug, Clone)]\npub struct IntoIter<T> {\n    inner: option::IntoIter<T>,\n}\n\nimpl<T: Send, E> IntoParallelIterator for Result<T, E> {\n    type Item = T;\n    type Iter = IntoIter<T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        IntoIter {\n            inner: self.ok().into_par_iter(),\n        }\n    }\n}\n\ndelegate_indexed_iterator! {\n    IntoIter<T> => T,\n    impl<T: Send>\n}\n\n/// Parallel iterator over an immutable reference to a result\n#[derive(Debug)]\npub struct Iter<'a, T> {\n    inner: option::IntoIter<&'a T>,\n}\n\nimpl<T> Clone for Iter<'_, T> {\n    fn clone(&self) -> Self {\n        Iter {\n            inner: self.inner.clone(),\n        }\n    }\n}\n\nimpl<'a, T: Sync, E> IntoParallelIterator for &'a Result<T, E> {\n    type Item = &'a T;\n    type Iter = Iter<'a, T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        Iter {\n            inner: self.as_ref().ok().into_par_iter(),\n        }\n    }\n}\n\ndelegate_indexed_iterator! {\n    Iter<'a, T> => &'a T,\n    impl<'a, T: Sync>\n}\n\n/// Parallel iterator over a mutable reference to a result\n#[derive(Debug)]\npub struct IterMut<'a, T> {\n    inner: option::IntoIter<&'a mut T>,\n}\n\nimpl<'a, T: Send, E> IntoParallelIterator for &'a mut Result<T, E> {\n    type Item = &'a mut T;\n    type Iter = IterMut<'a, T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        IterMut {\n            inner: self.as_mut().ok().into_par_iter(),\n        }\n    }\n}\n\ndelegate_indexed_iterator! {\n    IterMut<'a, T> => &'a mut T,\n    impl<'a, T: Send>\n}\n\n/// Collect an arbitrary `Result`-wrapped collection.\n///\n/// If any item is `Err`, then all previous `Ok` items collected are\n/// discarded, and it returns that error.  If there are multiple errors, the\n/// one returned is not deterministic.\nimpl<C, T, E> FromParallelIterator<Result<T, E>> for Result<C, E>\nwhere\n    C: FromParallelIterator<T>,\n    T: Send,\n    E: Send,\n{\n    fn from_par_iter<I>(par_iter: I) -> Self\n    where\n        I: IntoParallelIterator<Item = Result<T, E>>,\n    {\n        fn ok<T, E>(saved: &Mutex<Option<E>>) -> impl Fn(Result<T, E>) -> Option<T> + '_ {\n            move |item| match item {\n                Ok(item) => Some(item),\n                Err(error) => {\n                    // We don't need a blocking `lock()`, as anybody\n                    // else holding the lock will also be writing\n                    // `Some(error)`, and then ours is irrelevant.\n                    if let Ok(mut guard) = saved.try_lock() {\n                        if guard.is_none() {\n                            *guard = Some(error);\n                        }\n                    }\n                    None\n                }\n            }\n        }\n\n        let saved_error = Mutex::new(None);\n        let collection = par_iter\n            .into_par_iter()\n            .map(ok(&saved_error))\n            .while_some()\n            .collect();\n\n        match saved_error.into_inner().unwrap() {\n            Some(error) => Err(error),\n            None => Ok(collection),\n        }\n    }\n}\n"
  },
  {
    "path": "src/slice/chunk_by.rs",
    "content": "use crate::iter::plumbing::*;\nuse crate::iter::*;\nuse std::fmt;\nuse std::marker::PhantomData;\n\ntrait ChunkBySlice<T>: AsRef<[T]> + Default + Send {\n    fn split(self, index: usize) -> (Self, Self);\n    fn chunk_by(self, pred: &impl Fn(&T, &T) -> bool) -> impl Iterator<Item = Self>;\n\n    fn find(&self, pred: &impl Fn(&T, &T) -> bool, start: usize, end: usize) -> Option<usize> {\n        self.as_ref()[start..end]\n            .windows(2)\n            .position(move |w| !pred(&w[0], &w[1]))\n            .map(|i| i + 1)\n    }\n\n    fn rfind(&self, pred: &impl Fn(&T, &T) -> bool, end: usize) -> Option<usize> {\n        self.as_ref()[..end]\n            .windows(2)\n            .rposition(move |w| !pred(&w[0], &w[1]))\n            .map(|i| i + 1)\n    }\n}\n\nimpl<T: Sync> ChunkBySlice<T> for &[T] {\n    fn split(self, index: usize) -> (Self, Self) {\n        self.split_at(index)\n    }\n\n    fn chunk_by(self, pred: &impl Fn(&T, &T) -> bool) -> impl Iterator<Item = Self> {\n        self.chunk_by(pred)\n    }\n}\n\nimpl<T: Send> ChunkBySlice<T> for &mut [T] {\n    fn split(self, index: usize) -> (Self, Self) {\n        self.split_at_mut(index)\n    }\n\n    fn chunk_by(self, pred: &impl Fn(&T, &T) -> bool) -> impl Iterator<Item = Self> {\n        self.chunk_by_mut(pred)\n    }\n}\n\nstruct ChunkByProducer<'p, T, Slice, Pred> {\n    slice: Slice,\n    pred: &'p Pred,\n    tail: usize,\n    marker: PhantomData<fn(&T)>,\n}\n\n// Note: this implementation is very similar to `SplitProducer`.\nimpl<T, Slice, Pred> UnindexedProducer for ChunkByProducer<'_, T, Slice, Pred>\nwhere\n    Slice: ChunkBySlice<T>,\n    Pred: Fn(&T, &T) -> bool + Send + Sync,\n{\n    type Item = Slice;\n\n    fn split(self) -> (Self, Option<Self>) {\n        if self.tail < 2 {\n            return (Self { tail: 0, ..self }, None);\n        }\n\n        // Look forward for the separator, and failing that look backward.\n        let mid = self.tail / 2;\n        let index = match self.slice.find(self.pred, mid, self.tail) {\n            Some(i) => Some(mid + i),\n            None => self.slice.rfind(self.pred, mid + 1),\n        };\n\n        if let Some(index) = index {\n            let (left, right) = self.slice.split(index);\n\n            let (left_tail, right_tail) = if index <= mid {\n                // If we scanned backwards to find the separator, everything in\n                // the right side is exhausted, with no separators left to find.\n                (index, 0)\n            } else {\n                (mid + 1, self.tail - index)\n            };\n\n            // Create the left split before the separator.\n            let left = Self {\n                slice: left,\n                tail: left_tail,\n                ..self\n            };\n\n            // Create the right split following the separator.\n            let right = Self {\n                slice: right,\n                tail: right_tail,\n                ..self\n            };\n\n            (left, Some(right))\n        } else {\n            // The search is exhausted, no more separators...\n            (Self { tail: 0, ..self }, None)\n        }\n    }\n\n    fn fold_with<F>(self, mut folder: F) -> F\n    where\n        F: Folder<Self::Item>,\n    {\n        let Self {\n            slice, pred, tail, ..\n        } = self;\n\n        let (slice, tail) = if tail == slice.as_ref().len() {\n            // No tail section, so just let `consume_iter` do it all.\n            (Some(slice), None)\n        } else if let Some(index) = slice.rfind(pred, tail) {\n            // We found the last separator to complete the tail, so\n            // end with that slice after `consume_iter` finds the rest.\n            let (left, right) = slice.split(index);\n            (Some(left), Some(right))\n        } else {\n            // We know there are no separators at all, so it's all \"tail\".\n            (None, Some(slice))\n        };\n\n        if let Some(slice) = slice {\n            folder = folder.consume_iter(slice.chunk_by(pred));\n        }\n\n        if let Some(tail) = tail {\n            folder = folder.consume(tail);\n        }\n\n        folder\n    }\n}\n\n/// Parallel iterator over slice in (non-overlapping) chunks separated by a predicate.\n///\n/// This struct is created by the [`par_chunk_by`] method on `&[T]`.\n///\n/// [`par_chunk_by`]: super::ParallelSlice::par_chunk_by()\npub struct ChunkBy<'data, T, P> {\n    pred: P,\n    slice: &'data [T],\n}\n\nimpl<T, P: Clone> Clone for ChunkBy<'_, T, P> {\n    fn clone(&self) -> Self {\n        ChunkBy {\n            pred: self.pred.clone(),\n            slice: self.slice,\n        }\n    }\n}\n\nimpl<T: fmt::Debug, P> fmt::Debug for ChunkBy<'_, T, P> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"ChunkBy\")\n            .field(\"slice\", &self.slice)\n            .finish()\n    }\n}\n\nimpl<'data, T, P> ChunkBy<'data, T, P> {\n    pub(super) fn new(slice: &'data [T], pred: P) -> Self {\n        Self { pred, slice }\n    }\n}\n\nimpl<'data, T, P> ParallelIterator for ChunkBy<'data, T, P>\nwhere\n    T: Sync,\n    P: Fn(&T, &T) -> bool + Send + Sync,\n{\n    type Item = &'data [T];\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge_unindexed(\n            ChunkByProducer {\n                tail: self.slice.len(),\n                slice: self.slice,\n                pred: &self.pred,\n                marker: PhantomData,\n            },\n            consumer,\n        )\n    }\n}\n\n/// Parallel iterator over slice in (non-overlapping) mutable chunks\n/// separated by a predicate.\n///\n/// This struct is created by the [`par_chunk_by_mut`] method on `&mut [T]`.\n///\n/// [`par_chunk_by_mut`]: super::ParallelSliceMut::par_chunk_by_mut()\npub struct ChunkByMut<'data, T, P> {\n    pred: P,\n    slice: &'data mut [T],\n}\n\nimpl<T: fmt::Debug, P> fmt::Debug for ChunkByMut<'_, T, P> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"ChunkByMut\")\n            .field(\"slice\", &self.slice)\n            .finish()\n    }\n}\n\nimpl<'data, T, P> ChunkByMut<'data, T, P> {\n    pub(super) fn new(slice: &'data mut [T], pred: P) -> Self {\n        Self { pred, slice }\n    }\n}\n\nimpl<'data, T, P> ParallelIterator for ChunkByMut<'data, T, P>\nwhere\n    T: Send,\n    P: Fn(&T, &T) -> bool + Send + Sync,\n{\n    type Item = &'data mut [T];\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge_unindexed(\n            ChunkByProducer {\n                tail: self.slice.len(),\n                slice: self.slice,\n                pred: &self.pred,\n                marker: PhantomData,\n            },\n            consumer,\n        )\n    }\n}\n"
  },
  {
    "path": "src/slice/chunks.rs",
    "content": "use crate::iter::plumbing::*;\nuse crate::iter::*;\n\n/// Parallel iterator over immutable non-overlapping chunks of a slice\n#[derive(Debug)]\npub struct Chunks<'data, T> {\n    chunk_size: usize,\n    slice: &'data [T],\n}\n\nimpl<'data, T> Chunks<'data, T> {\n    pub(super) fn new(chunk_size: usize, slice: &'data [T]) -> Self {\n        Self { chunk_size, slice }\n    }\n}\n\nimpl<T> Clone for Chunks<'_, T> {\n    fn clone(&self) -> Self {\n        Chunks { ..*self }\n    }\n}\n\nimpl<'data, T: Sync> ParallelIterator for Chunks<'data, T> {\n    type Item = &'data [T];\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<T: Sync> IndexedParallelIterator for Chunks<'_, T> {\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.slice.len().div_ceil(self.chunk_size)\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        callback.callback(ChunksProducer {\n            chunk_size: self.chunk_size,\n            slice: self.slice,\n        })\n    }\n}\n\nstruct ChunksProducer<'data, T: Sync> {\n    chunk_size: usize,\n    slice: &'data [T],\n}\n\nimpl<'data, T: 'data + Sync> Producer for ChunksProducer<'data, T> {\n    type Item = &'data [T];\n    type IntoIter = ::std::slice::Chunks<'data, T>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.slice.chunks(self.chunk_size)\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let elem_index = Ord::min(index * self.chunk_size, self.slice.len());\n        let (left, right) = self.slice.split_at(elem_index);\n        (\n            ChunksProducer {\n                chunk_size: self.chunk_size,\n                slice: left,\n            },\n            ChunksProducer {\n                chunk_size: self.chunk_size,\n                slice: right,\n            },\n        )\n    }\n}\n\n/// Parallel iterator over immutable non-overlapping chunks of a slice\n#[derive(Debug)]\npub struct ChunksExact<'data, T> {\n    chunk_size: usize,\n    slice: &'data [T],\n    rem: &'data [T],\n}\n\nimpl<'data, T> ChunksExact<'data, T> {\n    pub(super) fn new(chunk_size: usize, slice: &'data [T]) -> Self {\n        let rem_len = slice.len() % chunk_size;\n        let len = slice.len() - rem_len;\n        let (slice, rem) = slice.split_at(len);\n        Self {\n            chunk_size,\n            slice,\n            rem,\n        }\n    }\n\n    /// Return the remainder of the original slice that is not going to be\n    /// returned by the iterator. The returned slice has at most `chunk_size-1`\n    /// elements.\n    pub fn remainder(&self) -> &'data [T] {\n        self.rem\n    }\n}\n\nimpl<T> Clone for ChunksExact<'_, T> {\n    fn clone(&self) -> Self {\n        ChunksExact { ..*self }\n    }\n}\n\nimpl<'data, T: Sync> ParallelIterator for ChunksExact<'data, T> {\n    type Item = &'data [T];\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<T: Sync> IndexedParallelIterator for ChunksExact<'_, T> {\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.slice.len() / self.chunk_size\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        callback.callback(ChunksExactProducer {\n            chunk_size: self.chunk_size,\n            slice: self.slice,\n        })\n    }\n}\n\nstruct ChunksExactProducer<'data, T: Sync> {\n    chunk_size: usize,\n    slice: &'data [T],\n}\n\nimpl<'data, T: 'data + Sync> Producer for ChunksExactProducer<'data, T> {\n    type Item = &'data [T];\n    type IntoIter = ::std::slice::ChunksExact<'data, T>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.slice.chunks_exact(self.chunk_size)\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let elem_index = index * self.chunk_size;\n        let (left, right) = self.slice.split_at(elem_index);\n        (\n            ChunksExactProducer {\n                chunk_size: self.chunk_size,\n                slice: left,\n            },\n            ChunksExactProducer {\n                chunk_size: self.chunk_size,\n                slice: right,\n            },\n        )\n    }\n}\n\n/// Parallel iterator over mutable non-overlapping chunks of a slice\n#[derive(Debug)]\npub struct ChunksMut<'data, T> {\n    chunk_size: usize,\n    slice: &'data mut [T],\n}\n\nimpl<'data, T> ChunksMut<'data, T> {\n    pub(super) fn new(chunk_size: usize, slice: &'data mut [T]) -> Self {\n        Self { chunk_size, slice }\n    }\n}\n\nimpl<'data, T: Send> ParallelIterator for ChunksMut<'data, T> {\n    type Item = &'data mut [T];\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<T: Send> IndexedParallelIterator for ChunksMut<'_, T> {\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.slice.len().div_ceil(self.chunk_size)\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        callback.callback(ChunksMutProducer {\n            chunk_size: self.chunk_size,\n            slice: self.slice,\n        })\n    }\n}\n\nstruct ChunksMutProducer<'data, T: Send> {\n    chunk_size: usize,\n    slice: &'data mut [T],\n}\n\nimpl<'data, T: 'data + Send> Producer for ChunksMutProducer<'data, T> {\n    type Item = &'data mut [T];\n    type IntoIter = ::std::slice::ChunksMut<'data, T>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.slice.chunks_mut(self.chunk_size)\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let elem_index = Ord::min(index * self.chunk_size, self.slice.len());\n        let (left, right) = self.slice.split_at_mut(elem_index);\n        (\n            ChunksMutProducer {\n                chunk_size: self.chunk_size,\n                slice: left,\n            },\n            ChunksMutProducer {\n                chunk_size: self.chunk_size,\n                slice: right,\n            },\n        )\n    }\n}\n\n/// Parallel iterator over mutable non-overlapping chunks of a slice\n#[derive(Debug)]\npub struct ChunksExactMut<'data, T> {\n    chunk_size: usize,\n    slice: &'data mut [T],\n    rem: &'data mut [T],\n}\n\nimpl<'data, T> ChunksExactMut<'data, T> {\n    pub(super) fn new(chunk_size: usize, slice: &'data mut [T]) -> Self {\n        let rem_len = slice.len() % chunk_size;\n        let len = slice.len() - rem_len;\n        let (slice, rem) = slice.split_at_mut(len);\n        Self {\n            chunk_size,\n            slice,\n            rem,\n        }\n    }\n\n    /// Return the remainder of the original slice that is not going to be\n    /// returned by the iterator. The returned slice has at most `chunk_size-1`\n    /// elements.\n    ///\n    /// Note that this has to consume `self` to return the original lifetime of\n    /// the data, which prevents this from actually being used as a parallel\n    /// iterator since that also consumes. This method is provided for parity\n    /// with `std::iter::ChunksExactMut`, but consider calling `remainder()` or\n    /// `take_remainder()` as alternatives.\n    pub fn into_remainder(self) -> &'data mut [T] {\n        self.rem\n    }\n\n    /// Return the remainder of the original slice that is not going to be\n    /// returned by the iterator. The returned slice has at most `chunk_size-1`\n    /// elements.\n    ///\n    /// Consider `take_remainder()` if you need access to the data with its\n    /// original lifetime, rather than borrowing through `&mut self` here.\n    pub fn remainder(&mut self) -> &mut [T] {\n        self.rem\n    }\n\n    /// Return the remainder of the original slice that is not going to be\n    /// returned by the iterator. The returned slice has at most `chunk_size-1`\n    /// elements. Subsequent calls will return an empty slice.\n    pub fn take_remainder(&mut self) -> &'data mut [T] {\n        std::mem::take(&mut self.rem)\n    }\n}\n\nimpl<'data, T: Send> ParallelIterator for ChunksExactMut<'data, T> {\n    type Item = &'data mut [T];\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<T: Send> IndexedParallelIterator for ChunksExactMut<'_, T> {\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.slice.len() / self.chunk_size\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        callback.callback(ChunksExactMutProducer {\n            chunk_size: self.chunk_size,\n            slice: self.slice,\n        })\n    }\n}\n\nstruct ChunksExactMutProducer<'data, T: Send> {\n    chunk_size: usize,\n    slice: &'data mut [T],\n}\n\nimpl<'data, T: 'data + Send> Producer for ChunksExactMutProducer<'data, T> {\n    type Item = &'data mut [T];\n    type IntoIter = ::std::slice::ChunksExactMut<'data, T>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.slice.chunks_exact_mut(self.chunk_size)\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let elem_index = index * self.chunk_size;\n        let (left, right) = self.slice.split_at_mut(elem_index);\n        (\n            ChunksExactMutProducer {\n                chunk_size: self.chunk_size,\n                slice: left,\n            },\n            ChunksExactMutProducer {\n                chunk_size: self.chunk_size,\n                slice: right,\n            },\n        )\n    }\n}\n"
  },
  {
    "path": "src/slice/mod.rs",
    "content": "//! Parallel iterator types for [slices]\n//!\n//! You will rarely need to interact with this module directly unless you need\n//! to name one of the iterator types.\n//!\n//! [slices]: std::slice\n\nmod chunk_by;\nmod chunks;\nmod rchunks;\nmod sort;\n\nmod test;\n\nuse self::sort::par_mergesort;\nuse self::sort::par_quicksort;\nuse crate::iter::plumbing::*;\nuse crate::iter::*;\nuse crate::split_producer::*;\n\nuse std::cmp::Ordering;\nuse std::fmt::{self, Debug};\n\npub use self::chunk_by::{ChunkBy, ChunkByMut};\npub use self::chunks::{Chunks, ChunksExact, ChunksExactMut, ChunksMut};\npub use self::rchunks::{RChunks, RChunksExact, RChunksExactMut, RChunksMut};\n\n/// Parallel extensions for slices.\npub trait ParallelSlice<T: Sync> {\n    /// Returns a plain slice, which is used to implement the rest of the\n    /// parallel methods.\n    fn as_parallel_slice(&self) -> &[T];\n\n    /// Returns a parallel iterator over subslices separated by elements that\n    /// match the separator.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let products: Vec<_> = [1, 2, 3, 0, 2, 4, 8, 0, 3, 6, 9]\n    ///     .par_split(|i| *i == 0)\n    ///     .map(|numbers| numbers.iter().product::<i32>())\n    ///     .collect();\n    /// assert_eq!(products, [6, 64, 162]);\n    /// ```\n    fn par_split<P>(&self, separator: P) -> Split<'_, T, P>\n    where\n        P: Fn(&T) -> bool + Sync + Send,\n    {\n        Split {\n            slice: self.as_parallel_slice(),\n            separator,\n        }\n    }\n\n    /// Returns a parallel iterator over subslices separated by elements that\n    /// match the separator, including the matched part as a terminator.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let lengths: Vec<_> = [1, 2, 3, 0, 2, 4, 8, 0, 3, 6, 9]\n    ///     .par_split_inclusive(|i| *i == 0)\n    ///     .map(|numbers| numbers.len())\n    ///     .collect();\n    /// assert_eq!(lengths, [4, 4, 3]);\n    /// ```\n    fn par_split_inclusive<P>(&self, separator: P) -> SplitInclusive<'_, T, P>\n    where\n        P: Fn(&T) -> bool + Sync + Send,\n    {\n        SplitInclusive {\n            slice: self.as_parallel_slice(),\n            separator,\n        }\n    }\n\n    /// Returns a parallel iterator over all contiguous windows of length\n    /// `window_size`. The windows overlap.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let windows: Vec<_> = [1, 2, 3].par_windows(2).collect();\n    /// assert_eq!(vec![[1, 2], [2, 3]], windows);\n    /// ```\n    fn par_windows(&self, window_size: usize) -> Windows<'_, T> {\n        Windows {\n            window_size,\n            slice: self.as_parallel_slice(),\n        }\n    }\n\n    /// Returns a parallel iterator over at most `chunk_size` elements of\n    /// `self` at a time. The chunks do not overlap.\n    ///\n    /// If the number of elements in the iterator is not divisible by\n    /// `chunk_size`, the last chunk may be shorter than `chunk_size`.  All\n    /// other chunks will have that exact length.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let chunks: Vec<_> = [1, 2, 3, 4, 5].par_chunks(2).collect();\n    /// assert_eq!(chunks, vec![&[1, 2][..], &[3, 4], &[5]]);\n    /// ```\n    #[track_caller]\n    fn par_chunks(&self, chunk_size: usize) -> Chunks<'_, T> {\n        assert!(chunk_size != 0, \"chunk_size must not be zero\");\n        Chunks::new(chunk_size, self.as_parallel_slice())\n    }\n\n    /// Returns a parallel iterator over `chunk_size` elements of\n    /// `self` at a time. The chunks do not overlap.\n    ///\n    /// If `chunk_size` does not divide the length of the slice, then the\n    /// last up to `chunk_size-1` elements will be omitted and can be\n    /// retrieved from the remainder function of the iterator.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let chunks: Vec<_> = [1, 2, 3, 4, 5].par_chunks_exact(2).collect();\n    /// assert_eq!(chunks, vec![&[1, 2][..], &[3, 4]]);\n    /// ```\n    #[track_caller]\n    fn par_chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> {\n        assert!(chunk_size != 0, \"chunk_size must not be zero\");\n        ChunksExact::new(chunk_size, self.as_parallel_slice())\n    }\n\n    /// Returns a parallel iterator over at most `chunk_size` elements of `self` at a time,\n    /// starting at the end. The chunks do not overlap.\n    ///\n    /// If the number of elements in the iterator is not divisible by\n    /// `chunk_size`, the last chunk may be shorter than `chunk_size`.  All\n    /// other chunks will have that exact length.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let chunks: Vec<_> = [1, 2, 3, 4, 5].par_rchunks(2).collect();\n    /// assert_eq!(chunks, vec![&[4, 5][..], &[2, 3], &[1]]);\n    /// ```\n    #[track_caller]\n    fn par_rchunks(&self, chunk_size: usize) -> RChunks<'_, T> {\n        assert!(chunk_size != 0, \"chunk_size must not be zero\");\n        RChunks::new(chunk_size, self.as_parallel_slice())\n    }\n\n    /// Returns a parallel iterator over `chunk_size` elements of `self` at a time,\n    /// starting at the end. The chunks do not overlap.\n    ///\n    /// If `chunk_size` does not divide the length of the slice, then the\n    /// last up to `chunk_size-1` elements will be omitted and can be\n    /// retrieved from the remainder function of the iterator.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let chunks: Vec<_> = [1, 2, 3, 4, 5].par_rchunks_exact(2).collect();\n    /// assert_eq!(chunks, vec![&[4, 5][..], &[2, 3]]);\n    /// ```\n    #[track_caller]\n    fn par_rchunks_exact(&self, chunk_size: usize) -> RChunksExact<'_, T> {\n        assert!(chunk_size != 0, \"chunk_size must not be zero\");\n        RChunksExact::new(chunk_size, self.as_parallel_slice())\n    }\n\n    /// Returns a parallel iterator over the slice producing non-overlapping runs\n    /// of elements using the predicate to separate them.\n    ///\n    /// The predicate is called on two elements following themselves,\n    /// it means the predicate is called on `slice[0]` and `slice[1]`\n    /// then on `slice[1]` and `slice[2]` and so on.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let chunks: Vec<_> = [1, 2, 2, 3, 3, 3].par_chunk_by(|&x, &y| x == y).collect();\n    /// assert_eq!(chunks[0], &[1]);\n    /// assert_eq!(chunks[1], &[2, 2]);\n    /// assert_eq!(chunks[2], &[3, 3, 3]);\n    /// ```\n    fn par_chunk_by<F>(&self, pred: F) -> ChunkBy<'_, T, F>\n    where\n        F: Fn(&T, &T) -> bool + Send + Sync,\n    {\n        ChunkBy::new(self.as_parallel_slice(), pred)\n    }\n}\n\nimpl<T: Sync> ParallelSlice<T> for [T] {\n    #[inline]\n    fn as_parallel_slice(&self) -> &[T] {\n        self\n    }\n}\n\n/// Parallel extensions for mutable slices.\npub trait ParallelSliceMut<T: Send> {\n    /// Returns a plain mutable slice, which is used to implement the rest of\n    /// the parallel methods.\n    fn as_parallel_slice_mut(&mut self) -> &mut [T];\n\n    /// Returns a parallel iterator over mutable subslices separated by\n    /// elements that match the separator.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let mut array = [1, 2, 3, 0, 2, 4, 8, 0, 3, 6, 9];\n    /// array.par_split_mut(|i| *i == 0)\n    ///      .for_each(|slice| slice.reverse());\n    /// assert_eq!(array, [3, 2, 1, 0, 8, 4, 2, 0, 9, 6, 3]);\n    /// ```\n    fn par_split_mut<P>(&mut self, separator: P) -> SplitMut<'_, T, P>\n    where\n        P: Fn(&T) -> bool + Sync + Send,\n    {\n        SplitMut {\n            slice: self.as_parallel_slice_mut(),\n            separator,\n        }\n    }\n\n    /// Returns a parallel iterator over mutable subslices separated by elements\n    /// that match the separator, including the matched part as a terminator.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let mut array = [1, 2, 3, 0, 2, 4, 8, 0, 3, 6, 9];\n    /// array.par_split_inclusive_mut(|i| *i == 0)\n    ///      .for_each(|slice| slice.reverse());\n    /// assert_eq!(array, [0, 3, 2, 1, 0, 8, 4, 2, 9, 6, 3]);\n    /// ```\n    fn par_split_inclusive_mut<P>(&mut self, separator: P) -> SplitInclusiveMut<'_, T, P>\n    where\n        P: Fn(&T) -> bool + Sync + Send,\n    {\n        SplitInclusiveMut {\n            slice: self.as_parallel_slice_mut(),\n            separator,\n        }\n    }\n\n    /// Returns a parallel iterator over at most `chunk_size` elements of\n    /// `self` at a time. The chunks are mutable and do not overlap.\n    ///\n    /// If the number of elements in the iterator is not divisible by\n    /// `chunk_size`, the last chunk may be shorter than `chunk_size`.  All\n    /// other chunks will have that exact length.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let mut array = [1, 2, 3, 4, 5];\n    /// array.par_chunks_mut(2)\n    ///      .for_each(|slice| slice.reverse());\n    /// assert_eq!(array, [2, 1, 4, 3, 5]);\n    /// ```\n    #[track_caller]\n    fn par_chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<'_, T> {\n        assert!(chunk_size != 0, \"chunk_size must not be zero\");\n        ChunksMut::new(chunk_size, self.as_parallel_slice_mut())\n    }\n\n    /// Returns a parallel iterator over `chunk_size` elements of\n    /// `self` at a time. The chunks are mutable and do not overlap.\n    ///\n    /// If `chunk_size` does not divide the length of the slice, then the\n    /// last up to `chunk_size-1` elements will be omitted and can be\n    /// retrieved from the remainder function of the iterator.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let mut array = [1, 2, 3, 4, 5];\n    /// array.par_chunks_exact_mut(3)\n    ///      .for_each(|slice| slice.reverse());\n    /// assert_eq!(array, [3, 2, 1, 4, 5]);\n    /// ```\n    #[track_caller]\n    fn par_chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_, T> {\n        assert!(chunk_size != 0, \"chunk_size must not be zero\");\n        ChunksExactMut::new(chunk_size, self.as_parallel_slice_mut())\n    }\n\n    /// Returns a parallel iterator over at most `chunk_size` elements of `self` at a time,\n    /// starting at the end. The chunks are mutable and do not overlap.\n    ///\n    /// If the number of elements in the iterator is not divisible by\n    /// `chunk_size`, the last chunk may be shorter than `chunk_size`.  All\n    /// other chunks will have that exact length.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let mut array = [1, 2, 3, 4, 5];\n    /// array.par_rchunks_mut(2)\n    ///      .for_each(|slice| slice.reverse());\n    /// assert_eq!(array, [1, 3, 2, 5, 4]);\n    /// ```\n    #[track_caller]\n    fn par_rchunks_mut(&mut self, chunk_size: usize) -> RChunksMut<'_, T> {\n        assert!(chunk_size != 0, \"chunk_size must not be zero\");\n        RChunksMut::new(chunk_size, self.as_parallel_slice_mut())\n    }\n\n    /// Returns a parallel iterator over `chunk_size` elements of `self` at a time,\n    /// starting at the end. The chunks are mutable and do not overlap.\n    ///\n    /// If `chunk_size` does not divide the length of the slice, then the\n    /// last up to `chunk_size-1` elements will be omitted and can be\n    /// retrieved from the remainder function of the iterator.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let mut array = [1, 2, 3, 4, 5];\n    /// array.par_rchunks_exact_mut(3)\n    ///      .for_each(|slice| slice.reverse());\n    /// assert_eq!(array, [1, 2, 5, 4, 3]);\n    /// ```\n    #[track_caller]\n    fn par_rchunks_exact_mut(&mut self, chunk_size: usize) -> RChunksExactMut<'_, T> {\n        assert!(chunk_size != 0, \"chunk_size must not be zero\");\n        RChunksExactMut::new(chunk_size, self.as_parallel_slice_mut())\n    }\n\n    /// Sorts the slice in parallel.\n    ///\n    /// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \\* log(*n*)) worst-case.\n    ///\n    /// When applicable, unstable sorting is preferred because it is generally faster than stable\n    /// sorting and it doesn't allocate auxiliary memory.\n    /// See [`par_sort_unstable`](#method.par_sort_unstable).\n    ///\n    /// # Current implementation\n    ///\n    /// The current algorithm is an adaptive merge sort inspired by\n    /// [timsort](https://en.wikipedia.org/wiki/Timsort).\n    /// It is designed to be very fast in cases where the slice is nearly sorted, or consists of\n    /// two or more sorted sequences concatenated one after another.\n    ///\n    /// Also, it allocates temporary storage the same size as `self`, but for very short slices a\n    /// non-allocating insertion sort is used instead.\n    ///\n    /// In order to sort the slice in parallel, the slice is first divided into smaller chunks and\n    /// all chunks are sorted in parallel. Then, adjacent chunks that together form non-descending\n    /// or descending runs are concatenated. Finally, the remaining chunks are merged together using\n    /// parallel subdivision of chunks and parallel merge operation.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let mut v = [-5, 4, 1, -3, 2];\n    ///\n    /// v.par_sort();\n    /// assert_eq!(v, [-5, -3, 1, 2, 4]);\n    /// ```\n    fn par_sort(&mut self)\n    where\n        T: Ord,\n    {\n        par_mergesort(self.as_parallel_slice_mut(), T::lt);\n    }\n\n    /// Sorts the slice in parallel with a comparator function.\n    ///\n    /// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \\* log(*n*)) worst-case.\n    ///\n    /// The comparator function must define a total ordering for the elements in the slice. If\n    /// the ordering is not total, the order of the elements is unspecified. An order is a\n    /// total order if it is (for all `a`, `b` and `c`):\n    ///\n    /// * total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is true, and\n    /// * transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.\n    ///\n    /// For example, while [`f64`] doesn't implement [`Ord`] because `NaN != NaN`, we can use\n    /// `partial_cmp` as our sort function when we know the slice doesn't contain a `NaN`.\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let mut floats = [5f64, 4.0, 1.0, 3.0, 2.0];\n    /// floats.par_sort_by(|a, b| a.partial_cmp(b).unwrap());\n    /// assert_eq!(floats, [1.0, 2.0, 3.0, 4.0, 5.0]);\n    /// ```\n    ///\n    /// When applicable, unstable sorting is preferred because it is generally faster than stable\n    /// sorting and it doesn't allocate auxiliary memory.\n    /// See [`par_sort_unstable_by`](#method.par_sort_unstable_by).\n    ///\n    /// # Current implementation\n    ///\n    /// The current algorithm is an adaptive merge sort inspired by\n    /// [timsort](https://en.wikipedia.org/wiki/Timsort).\n    /// It is designed to be very fast in cases where the slice is nearly sorted, or consists of\n    /// two or more sorted sequences concatenated one after another.\n    ///\n    /// Also, it allocates temporary storage the same size as `self`, but for very short slices a\n    /// non-allocating insertion sort is used instead.\n    ///\n    /// In order to sort the slice in parallel, the slice is first divided into smaller chunks and\n    /// all chunks are sorted in parallel. Then, adjacent chunks that together form non-descending\n    /// or descending runs are concatenated. Finally, the remaining chunks are merged together using\n    /// parallel subdivision of chunks and parallel merge operation.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let mut v = [5, 4, 1, 3, 2];\n    /// v.par_sort_by(|a, b| a.cmp(b));\n    /// assert_eq!(v, [1, 2, 3, 4, 5]);\n    ///\n    /// // reverse sorting\n    /// v.par_sort_by(|a, b| b.cmp(a));\n    /// assert_eq!(v, [5, 4, 3, 2, 1]);\n    /// ```\n    fn par_sort_by<F>(&mut self, compare: F)\n    where\n        F: Fn(&T, &T) -> Ordering + Sync,\n    {\n        par_mergesort(self.as_parallel_slice_mut(), |a, b| {\n            compare(a, b) == Ordering::Less\n        });\n    }\n\n    /// Sorts the slice in parallel with a key extraction function.\n    ///\n    /// This sort is stable (i.e., does not reorder equal elements) and *O*(*m* \\* *n* \\* log(*n*))\n    /// worst-case, where the key function is *O*(*m*).\n    ///\n    /// For expensive key functions (e.g. functions that are not simple property accesses or\n    /// basic operations), [`par_sort_by_cached_key`](#method.par_sort_by_cached_key) is likely to\n    /// be significantly faster, as it does not recompute element keys.\n    ///\n    /// When applicable, unstable sorting is preferred because it is generally faster than stable\n    /// sorting and it doesn't allocate auxiliary memory.\n    /// See [`par_sort_unstable_by_key`](#method.par_sort_unstable_by_key).\n    ///\n    /// # Current implementation\n    ///\n    /// The current algorithm is an adaptive merge sort inspired by\n    /// [timsort](https://en.wikipedia.org/wiki/Timsort).\n    /// It is designed to be very fast in cases where the slice is nearly sorted, or consists of\n    /// two or more sorted sequences concatenated one after another.\n    ///\n    /// Also, it allocates temporary storage the same size as `self`, but for very short slices a\n    /// non-allocating insertion sort is used instead.\n    ///\n    /// In order to sort the slice in parallel, the slice is first divided into smaller chunks and\n    /// all chunks are sorted in parallel. Then, adjacent chunks that together form non-descending\n    /// or descending runs are concatenated. Finally, the remaining chunks are merged together using\n    /// parallel subdivision of chunks and parallel merge operation.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let mut v = [-5i32, 4, 1, -3, 2];\n    ///\n    /// v.par_sort_by_key(|k| k.abs());\n    /// assert_eq!(v, [1, 2, -3, 4, -5]);\n    /// ```\n    fn par_sort_by_key<K, F>(&mut self, f: F)\n    where\n        K: Ord,\n        F: Fn(&T) -> K + Sync,\n    {\n        par_mergesort(self.as_parallel_slice_mut(), |a, b| f(a).lt(&f(b)));\n    }\n\n    /// Sorts the slice in parallel with a key extraction function.\n    ///\n    /// During sorting, the key function is called at most once per element, by using\n    /// temporary storage to remember the results of key evaluation.\n    /// The key function is called in parallel, so the order of calls is completely unspecified.\n    ///\n    /// This sort is stable (i.e., does not reorder equal elements) and *O*(*m* \\* *n* + *n* \\* log(*n*))\n    /// worst-case, where the key function is *O*(*m*).\n    ///\n    /// For simple key functions (e.g., functions that are property accesses or\n    /// basic operations), [`par_sort_by_key`](#method.par_sort_by_key) is likely to be\n    /// faster.\n    ///\n    /// # Current implementation\n    ///\n    /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters,\n    /// which combines the fast average case of randomized quicksort with the fast worst case of\n    /// heapsort, while achieving linear time on slices with certain patterns. It uses some\n    /// randomization to avoid degenerate cases, but with a fixed seed to always provide\n    /// deterministic behavior.\n    ///\n    /// In the worst case, the algorithm allocates temporary storage in a `Vec<(K, usize)>` the\n    /// length of the slice.\n    ///\n    /// All quicksorts work in two stages: partitioning into two halves followed by recursive\n    /// calls. The partitioning phase is sequential, but the two recursive calls are performed in\n    /// parallel. Finally, after sorting the cached keys, the item positions are updated sequentially.\n    ///\n    /// [pdqsort]: https://github.com/orlp/pdqsort\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let mut v = [-5i32, 4, 32, -3, 2];\n    ///\n    /// v.par_sort_by_cached_key(|k| k.to_string());\n    /// assert!(v == [-3, -5, 2, 32, 4]);\n    /// ```\n    fn par_sort_by_cached_key<K, F>(&mut self, f: F)\n    where\n        F: Fn(&T) -> K + Sync,\n        K: Ord + Send,\n    {\n        let slice = self.as_parallel_slice_mut();\n        let len = slice.len();\n        if len < 2 {\n            return;\n        }\n\n        // Helper macro for indexing our vector by the smallest possible type, to reduce allocation.\n        macro_rules! sort_by_key {\n            ($t:ty) => {{\n                let mut indices: Vec<_> = slice\n                    .par_iter_mut()\n                    .enumerate()\n                    .map(|(i, x)| (f(&*x), i as $t))\n                    .collect();\n                // The elements of `indices` are unique, as they are indexed, so any sort will be\n                // stable with respect to the original slice. We use `sort_unstable` here because\n                // it requires less memory allocation.\n                indices.par_sort_unstable();\n                for i in 0..len {\n                    let mut index = indices[i].1;\n                    while (index as usize) < i {\n                        index = indices[index as usize].1;\n                    }\n                    indices[i].1 = index;\n                    slice.swap(i, index as usize);\n                }\n            }};\n        }\n\n        let sz_u8 = size_of::<(K, u8)>();\n        let sz_u16 = size_of::<(K, u16)>();\n        let sz_u32 = size_of::<(K, u32)>();\n        let sz_usize = size_of::<(K, usize)>();\n\n        if sz_u8 < sz_u16 && len <= (u8::MAX as usize) {\n            return sort_by_key!(u8);\n        }\n        if sz_u16 < sz_u32 && len <= (u16::MAX as usize) {\n            return sort_by_key!(u16);\n        }\n        if sz_u32 < sz_usize && len <= (u32::MAX as usize) {\n            return sort_by_key!(u32);\n        }\n        sort_by_key!(usize)\n    }\n\n    /// Sorts the slice in parallel, but might not preserve the order of equal elements.\n    ///\n    /// This sort is unstable (i.e., may reorder equal elements), in-place\n    /// (i.e., does not allocate), and *O*(*n* \\* log(*n*)) worst-case.\n    ///\n    /// # Current implementation\n    ///\n    /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters,\n    /// which combines the fast average case of randomized quicksort with the fast worst case of\n    /// heapsort, while achieving linear time on slices with certain patterns. It uses some\n    /// randomization to avoid degenerate cases, but with a fixed seed to always provide\n    /// deterministic behavior.\n    ///\n    /// It is typically faster than stable sorting, except in a few special cases, e.g., when the\n    /// slice consists of several concatenated sorted sequences.\n    ///\n    /// All quicksorts work in two stages: partitioning into two halves followed by recursive\n    /// calls. The partitioning phase is sequential, but the two recursive calls are performed in\n    /// parallel.\n    ///\n    /// [pdqsort]: https://github.com/orlp/pdqsort\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let mut v = [-5, 4, 1, -3, 2];\n    ///\n    /// v.par_sort_unstable();\n    /// assert_eq!(v, [-5, -3, 1, 2, 4]);\n    /// ```\n    fn par_sort_unstable(&mut self)\n    where\n        T: Ord,\n    {\n        par_quicksort(self.as_parallel_slice_mut(), T::lt);\n    }\n\n    /// Sorts the slice in parallel with a comparator function, but might not preserve the order of\n    /// equal elements.\n    ///\n    /// This sort is unstable (i.e., may reorder equal elements), in-place\n    /// (i.e., does not allocate), and *O*(*n* \\* log(*n*)) worst-case.\n    ///\n    /// The comparator function must define a total ordering for the elements in the slice. If\n    /// the ordering is not total, the order of the elements is unspecified. An order is a\n    /// total order if it is (for all `a`, `b` and `c`):\n    ///\n    /// * total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is true, and\n    /// * transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.\n    ///\n    /// For example, while [`f64`] doesn't implement [`Ord`] because `NaN != NaN`, we can use\n    /// `partial_cmp` as our sort function when we know the slice doesn't contain a `NaN`.\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let mut floats = [5f64, 4.0, 1.0, 3.0, 2.0];\n    /// floats.par_sort_unstable_by(|a, b| a.partial_cmp(b).unwrap());\n    /// assert_eq!(floats, [1.0, 2.0, 3.0, 4.0, 5.0]);\n    /// ```\n    ///\n    /// # Current implementation\n    ///\n    /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters,\n    /// which combines the fast average case of randomized quicksort with the fast worst case of\n    /// heapsort, while achieving linear time on slices with certain patterns. It uses some\n    /// randomization to avoid degenerate cases, but with a fixed seed to always provide\n    /// deterministic behavior.\n    ///\n    /// It is typically faster than stable sorting, except in a few special cases, e.g., when the\n    /// slice consists of several concatenated sorted sequences.\n    ///\n    /// All quicksorts work in two stages: partitioning into two halves followed by recursive\n    /// calls. The partitioning phase is sequential, but the two recursive calls are performed in\n    /// parallel.\n    ///\n    /// [pdqsort]: https://github.com/orlp/pdqsort\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let mut v = [5, 4, 1, 3, 2];\n    /// v.par_sort_unstable_by(|a, b| a.cmp(b));\n    /// assert_eq!(v, [1, 2, 3, 4, 5]);\n    ///\n    /// // reverse sorting\n    /// v.par_sort_unstable_by(|a, b| b.cmp(a));\n    /// assert_eq!(v, [5, 4, 3, 2, 1]);\n    /// ```\n    fn par_sort_unstable_by<F>(&mut self, compare: F)\n    where\n        F: Fn(&T, &T) -> Ordering + Sync,\n    {\n        par_quicksort(self.as_parallel_slice_mut(), |a, b| {\n            compare(a, b) == Ordering::Less\n        });\n    }\n\n    /// Sorts the slice in parallel with a key extraction function, but might not preserve the order\n    /// of equal elements.\n    ///\n    /// This sort is unstable (i.e., may reorder equal elements), in-place\n    /// (i.e., does not allocate), and *O*(m \\* *n* \\* log(*n*)) worst-case,\n    /// where the key function is *O*(*m*).\n    ///\n    /// # Current implementation\n    ///\n    /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters,\n    /// which combines the fast average case of randomized quicksort with the fast worst case of\n    /// heapsort, while achieving linear time on slices with certain patterns. It uses some\n    /// randomization to avoid degenerate cases, but with a fixed seed to always provide\n    /// deterministic behavior.\n    ///\n    /// Due to its key calling strategy, `par_sort_unstable_by_key` is likely to be slower than\n    /// [`par_sort_by_cached_key`](#method.par_sort_by_cached_key) in cases where the key function\n    /// is expensive.\n    ///\n    /// All quicksorts work in two stages: partitioning into two halves followed by recursive\n    /// calls. The partitioning phase is sequential, but the two recursive calls are performed in\n    /// parallel.\n    ///\n    /// [pdqsort]: https://github.com/orlp/pdqsort\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let mut v = [-5i32, 4, 1, -3, 2];\n    ///\n    /// v.par_sort_unstable_by_key(|k| k.abs());\n    /// assert_eq!(v, [1, 2, -3, 4, -5]);\n    /// ```\n    fn par_sort_unstable_by_key<K, F>(&mut self, f: F)\n    where\n        K: Ord,\n        F: Fn(&T) -> K + Sync,\n    {\n        par_quicksort(self.as_parallel_slice_mut(), |a, b| f(a).lt(&f(b)));\n    }\n\n    /// Returns a parallel iterator over the slice producing non-overlapping mutable\n    /// runs of elements using the predicate to separate them.\n    ///\n    /// The predicate is called on two elements following themselves,\n    /// it means the predicate is called on `slice[0]` and `slice[1]`\n    /// then on `slice[1]` and `slice[2]` and so on.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let mut xs = [1, 2, 2, 3, 3, 3];\n    /// let chunks: Vec<_> = xs.par_chunk_by_mut(|&x, &y| x == y).collect();\n    /// assert_eq!(chunks[0], &mut [1]);\n    /// assert_eq!(chunks[1], &mut [2, 2]);\n    /// assert_eq!(chunks[2], &mut [3, 3, 3]);\n    /// ```\n    fn par_chunk_by_mut<F>(&mut self, pred: F) -> ChunkByMut<'_, T, F>\n    where\n        F: Fn(&T, &T) -> bool + Send + Sync,\n    {\n        ChunkByMut::new(self.as_parallel_slice_mut(), pred)\n    }\n}\n\nimpl<T: Send> ParallelSliceMut<T> for [T] {\n    #[inline]\n    fn as_parallel_slice_mut(&mut self) -> &mut [T] {\n        self\n    }\n}\n\nimpl<'data, T: Sync> IntoParallelIterator for &'data [T] {\n    type Item = &'data T;\n    type Iter = Iter<'data, T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        Iter { slice: self }\n    }\n}\n\nimpl<'data, T: Sync> IntoParallelIterator for &'data Box<[T]> {\n    type Item = &'data T;\n    type Iter = Iter<'data, T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        Iter { slice: self }\n    }\n}\n\nimpl<'data, T: Send> IntoParallelIterator for &'data mut [T] {\n    type Item = &'data mut T;\n    type Iter = IterMut<'data, T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        IterMut { slice: self }\n    }\n}\n\nimpl<'data, T: Send> IntoParallelIterator for &'data mut Box<[T]> {\n    type Item = &'data mut T;\n    type Iter = IterMut<'data, T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        IterMut { slice: self }\n    }\n}\n\n/// Parallel iterator over immutable items in a slice\n#[derive(Debug)]\npub struct Iter<'data, T> {\n    slice: &'data [T],\n}\n\nimpl<T> Clone for Iter<'_, T> {\n    fn clone(&self) -> Self {\n        Iter { ..*self }\n    }\n}\n\nimpl<'data, T: Sync> ParallelIterator for Iter<'data, T> {\n    type Item = &'data T;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<T: Sync> IndexedParallelIterator for Iter<'_, T> {\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.slice.len()\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        callback.callback(IterProducer { slice: self.slice })\n    }\n}\n\nstruct IterProducer<'data, T: Sync> {\n    slice: &'data [T],\n}\n\nimpl<'data, T: 'data + Sync> Producer for IterProducer<'data, T> {\n    type Item = &'data T;\n    type IntoIter = ::std::slice::Iter<'data, T>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.slice.iter()\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let (left, right) = self.slice.split_at(index);\n        (IterProducer { slice: left }, IterProducer { slice: right })\n    }\n}\n\n/// Parallel iterator over immutable overlapping windows of a slice\n#[derive(Debug)]\npub struct Windows<'data, T> {\n    window_size: usize,\n    slice: &'data [T],\n}\n\nimpl<T> Clone for Windows<'_, T> {\n    fn clone(&self) -> Self {\n        Windows { ..*self }\n    }\n}\n\nimpl<'data, T: Sync> ParallelIterator for Windows<'data, T> {\n    type Item = &'data [T];\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<T: Sync> IndexedParallelIterator for Windows<'_, T> {\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        assert!(self.window_size >= 1);\n        self.slice.len().saturating_sub(self.window_size - 1)\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        callback.callback(WindowsProducer {\n            window_size: self.window_size,\n            slice: self.slice,\n        })\n    }\n}\n\nstruct WindowsProducer<'data, T: Sync> {\n    window_size: usize,\n    slice: &'data [T],\n}\n\nimpl<'data, T: 'data + Sync> Producer for WindowsProducer<'data, T> {\n    type Item = &'data [T];\n    type IntoIter = ::std::slice::Windows<'data, T>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.slice.windows(self.window_size)\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let left_index = Ord::min(self.slice.len(), index + (self.window_size - 1));\n        let left = &self.slice[..left_index];\n        let right = &self.slice[index..];\n        (\n            WindowsProducer {\n                window_size: self.window_size,\n                slice: left,\n            },\n            WindowsProducer {\n                window_size: self.window_size,\n                slice: right,\n            },\n        )\n    }\n}\n\n/// Parallel iterator over mutable items in a slice\n#[derive(Debug)]\npub struct IterMut<'data, T> {\n    slice: &'data mut [T],\n}\n\nimpl<'data, T: Send> ParallelIterator for IterMut<'data, T> {\n    type Item = &'data mut T;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<T: Send> IndexedParallelIterator for IterMut<'_, T> {\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.slice.len()\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        callback.callback(IterMutProducer { slice: self.slice })\n    }\n}\n\nstruct IterMutProducer<'data, T: Send> {\n    slice: &'data mut [T],\n}\n\nimpl<'data, T: 'data + Send> Producer for IterMutProducer<'data, T> {\n    type Item = &'data mut T;\n    type IntoIter = ::std::slice::IterMut<'data, T>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.slice.iter_mut()\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let (left, right) = self.slice.split_at_mut(index);\n        (\n            IterMutProducer { slice: left },\n            IterMutProducer { slice: right },\n        )\n    }\n}\n\n/// Parallel iterator over slices separated by a predicate\npub struct Split<'data, T, P> {\n    slice: &'data [T],\n    separator: P,\n}\n\nimpl<T, P: Clone> Clone for Split<'_, T, P> {\n    fn clone(&self) -> Self {\n        Split {\n            separator: self.separator.clone(),\n            ..*self\n        }\n    }\n}\n\nimpl<T: Debug, P> Debug for Split<'_, T, P> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"Split\").field(\"slice\", &self.slice).finish()\n    }\n}\n\nimpl<'data, T, P> ParallelIterator for Split<'data, T, P>\nwhere\n    P: Fn(&T) -> bool + Sync + Send,\n    T: Sync,\n{\n    type Item = &'data [T];\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let producer = SplitProducer::new(self.slice, &self.separator);\n        bridge_unindexed(producer, consumer)\n    }\n}\n\n/// Parallel iterator over slices separated by a predicate,\n/// including the matched part as a terminator.\npub struct SplitInclusive<'data, T, P> {\n    slice: &'data [T],\n    separator: P,\n}\n\nimpl<T, P: Clone> Clone for SplitInclusive<'_, T, P> {\n    fn clone(&self) -> Self {\n        SplitInclusive {\n            separator: self.separator.clone(),\n            ..*self\n        }\n    }\n}\n\nimpl<T: Debug, P> Debug for SplitInclusive<'_, T, P> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"SplitInclusive\")\n            .field(\"slice\", &self.slice)\n            .finish()\n    }\n}\n\nimpl<'data, T, P> ParallelIterator for SplitInclusive<'data, T, P>\nwhere\n    P: Fn(&T) -> bool + Sync + Send,\n    T: Sync,\n{\n    type Item = &'data [T];\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let producer = SplitInclusiveProducer::new_incl(self.slice, &self.separator);\n        bridge_unindexed(producer, consumer)\n    }\n}\n\n/// Implement support for `SplitProducer`.\nimpl<T, P> Fissile<P> for &[T]\nwhere\n    P: Fn(&T) -> bool,\n{\n    fn length(&self) -> usize {\n        self.len()\n    }\n\n    fn midpoint(&self, end: usize) -> usize {\n        end / 2\n    }\n\n    fn find(&self, separator: &P, start: usize, end: usize) -> Option<usize> {\n        self[start..end].iter().position(separator)\n    }\n\n    fn rfind(&self, separator: &P, end: usize) -> Option<usize> {\n        self[..end].iter().rposition(separator)\n    }\n\n    fn split_once<const INCL: bool>(self, index: usize) -> (Self, Self) {\n        if INCL {\n            // include the separator in the left side\n            self.split_at(index + 1)\n        } else {\n            let (left, right) = self.split_at(index);\n            (left, &right[1..]) // skip the separator\n        }\n    }\n\n    fn fold_splits<F, const INCL: bool>(self, separator: &P, folder: F, skip_last: bool) -> F\n    where\n        F: Folder<Self>,\n        Self: Send,\n    {\n        if INCL {\n            debug_assert!(!skip_last);\n            folder.consume_iter(self.split_inclusive(separator))\n        } else {\n            let mut split = self.split(separator);\n            if skip_last {\n                split.next_back();\n            }\n            folder.consume_iter(split)\n        }\n    }\n}\n\n/// Parallel iterator over mutable slices separated by a predicate\npub struct SplitMut<'data, T, P> {\n    slice: &'data mut [T],\n    separator: P,\n}\n\nimpl<T: Debug, P> Debug for SplitMut<'_, T, P> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"SplitMut\")\n            .field(\"slice\", &self.slice)\n            .finish()\n    }\n}\n\nimpl<'data, T, P> ParallelIterator for SplitMut<'data, T, P>\nwhere\n    P: Fn(&T) -> bool + Sync + Send,\n    T: Send,\n{\n    type Item = &'data mut [T];\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let producer = SplitProducer::new(self.slice, &self.separator);\n        bridge_unindexed(producer, consumer)\n    }\n}\n\n/// Parallel iterator over mutable slices separated by a predicate,\n/// including the matched part as a terminator.\npub struct SplitInclusiveMut<'data, T, P> {\n    slice: &'data mut [T],\n    separator: P,\n}\n\nimpl<T: Debug, P> Debug for SplitInclusiveMut<'_, T, P> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"SplitInclusiveMut\")\n            .field(\"slice\", &self.slice)\n            .finish()\n    }\n}\n\nimpl<'data, T, P> ParallelIterator for SplitInclusiveMut<'data, T, P>\nwhere\n    P: Fn(&T) -> bool + Sync + Send,\n    T: Send,\n{\n    type Item = &'data mut [T];\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let producer = SplitInclusiveProducer::new_incl(self.slice, &self.separator);\n        bridge_unindexed(producer, consumer)\n    }\n}\n\n/// Implement support for `SplitProducer`.\nimpl<T, P> Fissile<P> for &mut [T]\nwhere\n    P: Fn(&T) -> bool,\n{\n    fn length(&self) -> usize {\n        self.len()\n    }\n\n    fn midpoint(&self, end: usize) -> usize {\n        end / 2\n    }\n\n    fn find(&self, separator: &P, start: usize, end: usize) -> Option<usize> {\n        self[start..end].iter().position(separator)\n    }\n\n    fn rfind(&self, separator: &P, end: usize) -> Option<usize> {\n        self[..end].iter().rposition(separator)\n    }\n\n    fn split_once<const INCL: bool>(self, index: usize) -> (Self, Self) {\n        if INCL {\n            // include the separator in the left side\n            self.split_at_mut(index + 1)\n        } else {\n            let (left, right) = self.split_at_mut(index);\n            (left, &mut right[1..]) // skip the separator\n        }\n    }\n\n    fn fold_splits<F, const INCL: bool>(self, separator: &P, folder: F, skip_last: bool) -> F\n    where\n        F: Folder<Self>,\n        Self: Send,\n    {\n        if INCL {\n            debug_assert!(!skip_last);\n            folder.consume_iter(self.split_inclusive_mut(separator))\n        } else {\n            let mut split = self.split_mut(separator);\n            if skip_last {\n                split.next_back();\n            }\n            folder.consume_iter(split)\n        }\n    }\n}\n"
  },
  {
    "path": "src/slice/rchunks.rs",
    "content": "use crate::iter::plumbing::*;\nuse crate::iter::*;\n\n/// Parallel iterator over immutable non-overlapping chunks of a slice, starting at the end.\n#[derive(Debug)]\npub struct RChunks<'data, T> {\n    chunk_size: usize,\n    slice: &'data [T],\n}\n\nimpl<'data, T> RChunks<'data, T> {\n    pub(super) fn new(chunk_size: usize, slice: &'data [T]) -> Self {\n        Self { chunk_size, slice }\n    }\n}\n\nimpl<T> Clone for RChunks<'_, T> {\n    fn clone(&self) -> Self {\n        RChunks { ..*self }\n    }\n}\n\nimpl<'data, T: Sync> ParallelIterator for RChunks<'data, T> {\n    type Item = &'data [T];\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<T: Sync> IndexedParallelIterator for RChunks<'_, T> {\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.slice.len().div_ceil(self.chunk_size)\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        callback.callback(RChunksProducer {\n            chunk_size: self.chunk_size,\n            slice: self.slice,\n        })\n    }\n}\n\nstruct RChunksProducer<'data, T: Sync> {\n    chunk_size: usize,\n    slice: &'data [T],\n}\n\nimpl<'data, T: 'data + Sync> Producer for RChunksProducer<'data, T> {\n    type Item = &'data [T];\n    type IntoIter = ::std::slice::RChunks<'data, T>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.slice.rchunks(self.chunk_size)\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let elem_index = self.slice.len().saturating_sub(index * self.chunk_size);\n        let (left, right) = self.slice.split_at(elem_index);\n        (\n            RChunksProducer {\n                chunk_size: self.chunk_size,\n                slice: right,\n            },\n            RChunksProducer {\n                chunk_size: self.chunk_size,\n                slice: left,\n            },\n        )\n    }\n}\n\n/// Parallel iterator over immutable non-overlapping chunks of a slice, starting at the end.\n#[derive(Debug)]\npub struct RChunksExact<'data, T> {\n    chunk_size: usize,\n    slice: &'data [T],\n    rem: &'data [T],\n}\n\nimpl<'data, T> RChunksExact<'data, T> {\n    pub(super) fn new(chunk_size: usize, slice: &'data [T]) -> Self {\n        let rem_len = slice.len() % chunk_size;\n        let (rem, slice) = slice.split_at(rem_len);\n        Self {\n            chunk_size,\n            slice,\n            rem,\n        }\n    }\n\n    /// Return the remainder of the original slice that is not going to be\n    /// returned by the iterator. The returned slice has at most `chunk_size-1`\n    /// elements.\n    pub fn remainder(&self) -> &'data [T] {\n        self.rem\n    }\n}\n\nimpl<T> Clone for RChunksExact<'_, T> {\n    fn clone(&self) -> Self {\n        RChunksExact { ..*self }\n    }\n}\n\nimpl<'data, T: Sync> ParallelIterator for RChunksExact<'data, T> {\n    type Item = &'data [T];\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<T: Sync> IndexedParallelIterator for RChunksExact<'_, T> {\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.slice.len() / self.chunk_size\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        callback.callback(RChunksExactProducer {\n            chunk_size: self.chunk_size,\n            slice: self.slice,\n        })\n    }\n}\n\nstruct RChunksExactProducer<'data, T: Sync> {\n    chunk_size: usize,\n    slice: &'data [T],\n}\n\nimpl<'data, T: 'data + Sync> Producer for RChunksExactProducer<'data, T> {\n    type Item = &'data [T];\n    type IntoIter = ::std::slice::RChunksExact<'data, T>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.slice.rchunks_exact(self.chunk_size)\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let elem_index = self.slice.len() - index * self.chunk_size;\n        let (left, right) = self.slice.split_at(elem_index);\n        (\n            RChunksExactProducer {\n                chunk_size: self.chunk_size,\n                slice: right,\n            },\n            RChunksExactProducer {\n                chunk_size: self.chunk_size,\n                slice: left,\n            },\n        )\n    }\n}\n\n/// Parallel iterator over mutable non-overlapping chunks of a slice, starting at the end.\n#[derive(Debug)]\npub struct RChunksMut<'data, T> {\n    chunk_size: usize,\n    slice: &'data mut [T],\n}\n\nimpl<'data, T> RChunksMut<'data, T> {\n    pub(super) fn new(chunk_size: usize, slice: &'data mut [T]) -> Self {\n        Self { chunk_size, slice }\n    }\n}\n\nimpl<'data, T: Send> ParallelIterator for RChunksMut<'data, T> {\n    type Item = &'data mut [T];\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<T: Send> IndexedParallelIterator for RChunksMut<'_, T> {\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.slice.len().div_ceil(self.chunk_size)\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        callback.callback(RChunksMutProducer {\n            chunk_size: self.chunk_size,\n            slice: self.slice,\n        })\n    }\n}\n\nstruct RChunksMutProducer<'data, T: Send> {\n    chunk_size: usize,\n    slice: &'data mut [T],\n}\n\nimpl<'data, T: 'data + Send> Producer for RChunksMutProducer<'data, T> {\n    type Item = &'data mut [T];\n    type IntoIter = ::std::slice::RChunksMut<'data, T>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.slice.rchunks_mut(self.chunk_size)\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let elem_index = self.slice.len().saturating_sub(index * self.chunk_size);\n        let (left, right) = self.slice.split_at_mut(elem_index);\n        (\n            RChunksMutProducer {\n                chunk_size: self.chunk_size,\n                slice: right,\n            },\n            RChunksMutProducer {\n                chunk_size: self.chunk_size,\n                slice: left,\n            },\n        )\n    }\n}\n\n/// Parallel iterator over mutable non-overlapping chunks of a slice, starting at the end.\n#[derive(Debug)]\npub struct RChunksExactMut<'data, T: Send> {\n    chunk_size: usize,\n    slice: &'data mut [T],\n    rem: &'data mut [T],\n}\n\nimpl<'data, T: Send> RChunksExactMut<'data, T> {\n    pub(super) fn new(chunk_size: usize, slice: &'data mut [T]) -> Self {\n        let rem_len = slice.len() % chunk_size;\n        let (rem, slice) = slice.split_at_mut(rem_len);\n        Self {\n            chunk_size,\n            slice,\n            rem,\n        }\n    }\n\n    /// Return the remainder of the original slice that is not going to be\n    /// returned by the iterator. The returned slice has at most `chunk_size-1`\n    /// elements.\n    ///\n    /// Note that this has to consume `self` to return the original lifetime of\n    /// the data, which prevents this from actually being used as a parallel\n    /// iterator since that also consumes. This method is provided for parity\n    /// with `std::iter::RChunksExactMut`, but consider calling `remainder()` or\n    /// `take_remainder()` as alternatives.\n    pub fn into_remainder(self) -> &'data mut [T] {\n        self.rem\n    }\n\n    /// Return the remainder of the original slice that is not going to be\n    /// returned by the iterator. The returned slice has at most `chunk_size-1`\n    /// elements.\n    ///\n    /// Consider `take_remainder()` if you need access to the data with its\n    /// original lifetime, rather than borrowing through `&mut self` here.\n    pub fn remainder(&mut self) -> &mut [T] {\n        self.rem\n    }\n\n    /// Return the remainder of the original slice that is not going to be\n    /// returned by the iterator. The returned slice has at most `chunk_size-1`\n    /// elements. Subsequent calls will return an empty slice.\n    pub fn take_remainder(&mut self) -> &'data mut [T] {\n        std::mem::take(&mut self.rem)\n    }\n}\n\nimpl<'data, T: Send + 'data> ParallelIterator for RChunksExactMut<'data, T> {\n    type Item = &'data mut [T];\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<'data, T: Send + 'data> IndexedParallelIterator for RChunksExactMut<'data, T> {\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.slice.len() / self.chunk_size\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        callback.callback(RChunksExactMutProducer {\n            chunk_size: self.chunk_size,\n            slice: self.slice,\n        })\n    }\n}\n\nstruct RChunksExactMutProducer<'data, T: Send> {\n    chunk_size: usize,\n    slice: &'data mut [T],\n}\n\nimpl<'data, T: 'data + Send> Producer for RChunksExactMutProducer<'data, T> {\n    type Item = &'data mut [T];\n    type IntoIter = ::std::slice::RChunksExactMut<'data, T>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.slice.rchunks_exact_mut(self.chunk_size)\n    }\n\n    fn split_at(self, index: usize) -> (Self, Self) {\n        let elem_index = self.slice.len() - index * self.chunk_size;\n        let (left, right) = self.slice.split_at_mut(elem_index);\n        (\n            RChunksExactMutProducer {\n                chunk_size: self.chunk_size,\n                slice: right,\n            },\n            RChunksExactMutProducer {\n                chunk_size: self.chunk_size,\n                slice: left,\n            },\n        )\n    }\n}\n"
  },
  {
    "path": "src/slice/sort.rs",
    "content": "//! **Parallel** Slice sorting\n//!\n//! This implementation is mostly copied from the `core::slice::sort` module, with minimal changes\n//! to support stable Rust and parallel `is_less` (e.g. `Fn` rather than `FnMut`).\n//!\n//! ---\n//!\n//! This module contains a sorting algorithm based on Orson Peters' pattern-defeating quicksort,\n//! published at: <https://github.com/orlp/pdqsort>\n//!\n//! Unstable sorting is compatible with core because it doesn't allocate memory, unlike our\n//! stable sorting implementation.\n//!\n//! In addition it also contains the core logic of the stable sort used by `slice::sort` based on\n//! TimSort.\n\nuse core::cmp;\nuse core::mem::{self, MaybeUninit};\nuse core::ptr;\nuse core::slice;\n\nuse crate::iter::{IndexedParallelIterator, ParallelIterator};\nuse crate::slice::ParallelSliceMut;\nuse crate::SendPtr;\n\n// When dropped, copies from `src` into `dest`.\nstruct InsertionHole<T> {\n    src: *const T,\n    dest: *mut T,\n}\n\nimpl<T> Drop for InsertionHole<T> {\n    fn drop(&mut self) {\n        // SAFETY: This is a helper class. Please refer to its usage for correctness. Namely, one\n        // must be sure that `src` and `dst` does not overlap as required by\n        // `ptr::copy_nonoverlapping` and are both valid for writes.\n        unsafe {\n            ptr::copy_nonoverlapping(self.src, self.dest, 1);\n        }\n    }\n}\n\n/// Inserts `v[v.len() - 1]` into pre-sorted sequence `v[..v.len() - 1]` so that whole `v[..]`\n/// becomes sorted.\nunsafe fn insert_tail<T, F>(v: &mut [T], is_less: &F)\nwhere\n    F: Fn(&T, &T) -> bool,\n{\n    debug_assert!(v.len() >= 2);\n\n    let arr_ptr = v.as_mut_ptr();\n    let i = v.len() - 1;\n\n    // SAFETY: caller must ensure v is at least len 2.\n    unsafe {\n        // See insert_head which talks about why this approach is beneficial.\n        let i_ptr = arr_ptr.add(i);\n\n        // It's important that we use i_ptr here. If this check is positive and we continue,\n        // We want to make sure that no other copy of the value was seen by is_less.\n        // Otherwise we would have to copy it back.\n        if is_less(&*i_ptr, &*i_ptr.sub(1)) {\n            // It's important, that we use tmp for comparison from now on. As it is the value that\n            // will be copied back. And notionally we could have created a divergence if we copy\n            // back the wrong value.\n            let tmp = mem::ManuallyDrop::new(ptr::read(i_ptr));\n            // Intermediate state of the insertion process is always tracked by `hole`, which\n            // serves two purposes:\n            // 1. Protects integrity of `v` from panics in `is_less`.\n            // 2. Fills the remaining hole in `v` in the end.\n            //\n            // Panic safety:\n            //\n            // If `is_less` panics at any point during the process, `hole` will get dropped and\n            // fill the hole in `v` with `tmp`, thus ensuring that `v` still holds every object it\n            // initially held exactly once.\n            let mut hole = InsertionHole {\n                src: &*tmp,\n                dest: i_ptr.sub(1),\n            };\n            ptr::copy_nonoverlapping(hole.dest, i_ptr, 1);\n\n            // SAFETY: We know i is at least 1.\n            for j in (0..(i - 1)).rev() {\n                let j_ptr = arr_ptr.add(j);\n                if !is_less(&*tmp, &*j_ptr) {\n                    break;\n                }\n\n                ptr::copy_nonoverlapping(j_ptr, hole.dest, 1);\n                hole.dest = j_ptr;\n            }\n            // `hole` gets dropped and thus copies `tmp` into the remaining hole in `v`.\n        }\n    }\n}\n\n/// Inserts `v[0]` into pre-sorted sequence `v[1..]` so that whole `v[..]` becomes sorted.\n///\n/// This is the integral subroutine of insertion sort.\nunsafe fn insert_head<T, F>(v: &mut [T], is_less: &F)\nwhere\n    F: Fn(&T, &T) -> bool,\n{\n    debug_assert!(v.len() >= 2);\n\n    // SAFETY: caller must ensure v is at least len 2.\n    unsafe {\n        if is_less(v.get_unchecked(1), v.get_unchecked(0)) {\n            let arr_ptr = v.as_mut_ptr();\n\n            // There are three ways to implement insertion here:\n            //\n            // 1. Swap adjacent elements until the first one gets to its final destination.\n            //    However, this way we copy data around more than is necessary. If elements are big\n            //    structures (costly to copy), this method will be slow.\n            //\n            // 2. Iterate until the right place for the first element is found. Then shift the\n            //    elements succeeding it to make room for it and finally place it into the\n            //    remaining hole. This is a good method.\n            //\n            // 3. Copy the first element into a temporary variable. Iterate until the right place\n            //    for it is found. As we go along, copy every traversed element into the slot\n            //    preceding it. Finally, copy data from the temporary variable into the remaining\n            //    hole. This method is very good. Benchmarks demonstrated slightly better\n            //    performance than with the 2nd method.\n            //\n            // All methods were benchmarked, and the 3rd showed best results. So we chose that one.\n            let tmp = mem::ManuallyDrop::new(ptr::read(arr_ptr));\n\n            // Intermediate state of the insertion process is always tracked by `hole`, which\n            // serves two purposes:\n            // 1. Protects integrity of `v` from panics in `is_less`.\n            // 2. Fills the remaining hole in `v` in the end.\n            //\n            // Panic safety:\n            //\n            // If `is_less` panics at any point during the process, `hole` will get dropped and\n            // fill the hole in `v` with `tmp`, thus ensuring that `v` still holds every object it\n            // initially held exactly once.\n            let mut hole = InsertionHole {\n                src: &*tmp,\n                dest: arr_ptr.add(1),\n            };\n            ptr::copy_nonoverlapping(arr_ptr.add(1), arr_ptr.add(0), 1);\n\n            for i in 2..v.len() {\n                if !is_less(v.get_unchecked(i), &*tmp) {\n                    break;\n                }\n                ptr::copy_nonoverlapping(arr_ptr.add(i), arr_ptr.add(i - 1), 1);\n                hole.dest = arr_ptr.add(i);\n            }\n            // `hole` gets dropped and thus copies `tmp` into the remaining hole in `v`.\n        }\n    }\n}\n\n/// Sort `v` assuming `v[..offset]` is already sorted.\n///\n/// Never inline this function to avoid code bloat. It still optimizes nicely and has practically no\n/// performance impact. Even improving performance in some cases.\n#[inline(never)]\nfn insertion_sort_shift_left<T, F>(v: &mut [T], offset: usize, is_less: &F)\nwhere\n    F: Fn(&T, &T) -> bool,\n{\n    let len = v.len();\n\n    // Using assert here improves performance.\n    assert!(offset != 0 && offset <= len);\n\n    // Shift each element of the unsorted region v[i..] as far left as is needed to make v sorted.\n    for i in offset..len {\n        // SAFETY: we tested that `offset` must be at least 1, so this loop is only entered if len\n        // >= 2. The range is exclusive and we know `i` must be at least 1 so this slice has at\n        // >least len 2.\n        unsafe {\n            insert_tail(&mut v[..=i], is_less);\n        }\n    }\n}\n\n/// Sort `v` assuming `v[offset..]` is already sorted.\n///\n/// Never inline this function to avoid code bloat. It still optimizes nicely and has practically no\n/// performance impact. Even improving performance in some cases.\n#[inline(never)]\nfn insertion_sort_shift_right<T, F>(v: &mut [T], offset: usize, is_less: &F)\nwhere\n    F: Fn(&T, &T) -> bool,\n{\n    let len = v.len();\n\n    // Using assert here improves performance.\n    assert!(offset != 0 && offset <= len && len >= 2);\n\n    // Shift each element of the unsorted region v[..i] as far left as is needed to make v sorted.\n    for i in (0..offset).rev() {\n        // SAFETY: we tested that `offset` must be at least 1, so this loop is only entered if len\n        // >= 2.We ensured that the slice length is always at least 2 long. We know that start_found\n        // will be at least one less than end, and the range is exclusive. Which gives us i always\n        // <= (end - 2).\n        unsafe {\n            insert_head(&mut v[i..len], is_less);\n        }\n    }\n}\n\n/// Partially sorts a slice by shifting several out-of-order elements around.\n///\n/// Returns `true` if the slice is sorted at the end. This function is *O*(*n*) worst-case.\n#[cold]\nfn partial_insertion_sort<T, F>(v: &mut [T], is_less: &F) -> bool\nwhere\n    F: Fn(&T, &T) -> bool,\n{\n    // Maximum number of adjacent out-of-order pairs that will get shifted.\n    const MAX_STEPS: usize = 5;\n    // If the slice is shorter than this, don't shift any elements.\n    const SHORTEST_SHIFTING: usize = 50;\n\n    let len = v.len();\n    let mut i = 1;\n\n    for _ in 0..MAX_STEPS {\n        // SAFETY: We already explicitly did the bound checking with `i < len`.\n        // All our subsequent indexing is only in the range `0 <= index < len`\n        unsafe {\n            // Find the next pair of adjacent out-of-order elements.\n            while i < len && !is_less(v.get_unchecked(i), v.get_unchecked(i - 1)) {\n                i += 1;\n            }\n        }\n\n        // Are we done?\n        if i == len {\n            return true;\n        }\n\n        // Don't shift elements on short arrays, that has a performance cost.\n        if len < SHORTEST_SHIFTING {\n            return false;\n        }\n\n        // Swap the found pair of elements. This puts them in correct order.\n        v.swap(i - 1, i);\n\n        if i >= 2 {\n            // Shift the smaller element to the left.\n            insertion_sort_shift_left(&mut v[..i], i - 1, is_less);\n\n            // Shift the greater element to the right.\n            insertion_sort_shift_right(&mut v[..i], 1, is_less);\n        }\n    }\n\n    // Didn't manage to sort the slice in the limited number of steps.\n    false\n}\n\n/// Sorts `v` using heapsort, which guarantees *O*(*n* \\* log(*n*)) worst-case.\n#[cold]\nfn heapsort<T, F>(v: &mut [T], is_less: F)\nwhere\n    F: Fn(&T, &T) -> bool,\n{\n    // This binary heap respects the invariant `parent >= child`.\n    let sift_down = |v: &mut [T], mut node| {\n        loop {\n            // Children of `node`.\n            let mut child = 2 * node + 1;\n            if child >= v.len() {\n                break;\n            }\n\n            // Choose the greater child.\n            if child + 1 < v.len() {\n                // We need a branch to be sure not to out-of-bounds index,\n                // but it's highly predictable.  The comparison, however,\n                // is better done branchless, especially for primitives.\n                child += is_less(&v[child], &v[child + 1]) as usize;\n            }\n\n            // Stop if the invariant holds at `node`.\n            if !is_less(&v[node], &v[child]) {\n                break;\n            }\n\n            // Swap `node` with the greater child, move one step down, and continue sifting.\n            v.swap(node, child);\n            node = child;\n        }\n    };\n\n    // Build the heap in linear time.\n    for i in (0..v.len() / 2).rev() {\n        sift_down(v, i);\n    }\n\n    // Pop maximal elements from the heap.\n    for i in (1..v.len()).rev() {\n        v.swap(0, i);\n        sift_down(&mut v[..i], 0);\n    }\n}\n\n/// Partitions `v` into elements smaller than `pivot`, followed by elements greater than or equal\n/// to `pivot`.\n///\n/// Returns the number of elements smaller than `pivot`.\n///\n/// Partitioning is performed block-by-block in order to minimize the cost of branching operations.\n/// This idea is presented in the [BlockQuicksort][pdf] paper.\n///\n/// [pdf]: https://drops.dagstuhl.de/opus/volltexte/2016/6389/pdf/LIPIcs-ESA-2016-38.pdf\nfn partition_in_blocks<T, F>(v: &mut [T], pivot: &T, is_less: &F) -> usize\nwhere\n    F: Fn(&T, &T) -> bool,\n{\n    // Number of elements in a typical block.\n    const BLOCK: usize = 128;\n\n    // The partitioning algorithm repeats the following steps until completion:\n    //\n    // 1. Trace a block from the left side to identify elements greater than or equal to the pivot.\n    // 2. Trace a block from the right side to identify elements smaller than the pivot.\n    // 3. Exchange the identified elements between the left and right side.\n    //\n    // We keep the following variables for a block of elements:\n    //\n    // 1. `block` - Number of elements in the block.\n    // 2. `start` - Start pointer into the `offsets` array.\n    // 3. `end` - End pointer into the `offsets` array.\n    // 4. `offsets` - Indices of out-of-order elements within the block.\n\n    // The current block on the left side (from `l` to `l.add(block_l)`).\n    let mut l = v.as_mut_ptr();\n    let mut block_l = BLOCK;\n    let mut start_l = ptr::null_mut();\n    let mut end_l = ptr::null_mut();\n    let mut offsets_l = [MaybeUninit::<u8>::uninit(); BLOCK];\n\n    // The current block on the right side (from `r.sub(block_r)` to `r`).\n    // SAFETY: The documentation for .add() specifically mention that `vec.as_ptr().add(vec.len())` is always safe\n    let mut r = unsafe { l.add(v.len()) };\n    let mut block_r = BLOCK;\n    let mut start_r = ptr::null_mut();\n    let mut end_r = ptr::null_mut();\n    let mut offsets_r = [MaybeUninit::<u8>::uninit(); BLOCK];\n\n    // FIXME: When we get VLAs, try creating one array of length `min(v.len(), 2 * BLOCK)` rather\n    // than two fixed-size arrays of length `BLOCK`. VLAs might be more cache-efficient.\n\n    // Returns the number of elements between pointers `l` (inclusive) and `r` (exclusive).\n    fn width<T>(l: *mut T, r: *mut T) -> usize {\n        assert!(size_of::<T>() > 0);\n        // FIXME: this should *likely* use `offset_from`, but more\n        // investigation is needed (including running tests in miri).\n        (r as usize - l as usize) / size_of::<T>()\n    }\n\n    loop {\n        // We are done with partitioning block-by-block when `l` and `r` get very close. Then we do\n        // some patch-up work in order to partition the remaining elements in between.\n        let is_done = width(l, r) <= 2 * BLOCK;\n\n        if is_done {\n            // Number of remaining elements (still not compared to the pivot).\n            let mut rem = width(l, r);\n            if start_l < end_l || start_r < end_r {\n                rem -= BLOCK;\n            }\n\n            // Adjust block sizes so that the left and right block don't overlap, but get perfectly\n            // aligned to cover the whole remaining gap.\n            if start_l < end_l {\n                block_r = rem;\n            } else if start_r < end_r {\n                block_l = rem;\n            } else {\n                // There were the same number of elements to switch on both blocks during the last\n                // iteration, so there are no remaining elements on either block. Cover the remaining\n                // items with roughly equally-sized blocks.\n                block_l = rem / 2;\n                block_r = rem - block_l;\n            }\n            debug_assert!(block_l <= BLOCK && block_r <= BLOCK);\n            debug_assert!(width(l, r) == block_l + block_r);\n        }\n\n        if start_l == end_l {\n            // Trace `block_l` elements from the left side.\n            start_l = offsets_l.as_mut_ptr() as *mut u8;\n            end_l = start_l;\n            let mut elem = l;\n\n            for i in 0..block_l {\n                // SAFETY: The unsafety operations below involve the usage of the `offset`.\n                //         According to the conditions required by the function, we satisfy them because:\n                //         1. `offsets_l` is stack-allocated, and thus considered separate allocated object.\n                //         2. The function `is_less` returns a `bool`.\n                //            Casting a `bool` will never overflow `isize`.\n                //         3. We have guaranteed that `block_l` will be `<= BLOCK`.\n                //            Plus, `end_l` was initially set to the begin pointer of `offsets_` which was declared on the stack.\n                //            Thus, we know that even in the worst case (all invocations of `is_less` returns false) we will only be at most 1 byte pass the end.\n                //        Another unsafety operation here is dereferencing `elem`.\n                //        However, `elem` was initially the begin pointer to the slice which is always valid.\n                unsafe {\n                    // Branchless comparison.\n                    *end_l = i as u8;\n                    end_l = end_l.add(!is_less(&*elem, pivot) as usize);\n                    elem = elem.add(1);\n                }\n            }\n        }\n\n        if start_r == end_r {\n            // Trace `block_r` elements from the right side.\n            start_r = offsets_r.as_mut_ptr() as *mut u8;\n            end_r = start_r;\n            let mut elem = r;\n\n            for i in 0..block_r {\n                // SAFETY: The unsafety operations below involve the usage of the `offset`.\n                //         According to the conditions required by the function, we satisfy them because:\n                //         1. `offsets_r` is stack-allocated, and thus considered separate allocated object.\n                //         2. The function `is_less` returns a `bool`.\n                //            Casting a `bool` will never overflow `isize`.\n                //         3. We have guaranteed that `block_r` will be `<= BLOCK`.\n                //            Plus, `end_r` was initially set to the begin pointer of `offsets_` which was declared on the stack.\n                //            Thus, we know that even in the worst case (all invocations of `is_less` returns true) we will only be at most 1 byte pass the end.\n                //        Another unsafety operation here is dereferencing `elem`.\n                //        However, `elem` was initially `1 * sizeof(T)` past the end and we decrement it by `1 * sizeof(T)` before accessing it.\n                //        Plus, `block_r` was asserted to be less than `BLOCK` and `elem` will therefore at most be pointing to the beginning of the slice.\n                unsafe {\n                    // Branchless comparison.\n                    elem = elem.sub(1);\n                    *end_r = i as u8;\n                    end_r = end_r.add(is_less(&*elem, pivot) as usize);\n                }\n            }\n        }\n\n        // Number of out-of-order elements to swap between the left and right side.\n        let count = cmp::min(width(start_l, end_l), width(start_r, end_r));\n\n        if count > 0 {\n            macro_rules! left {\n                () => {\n                    l.add(usize::from(*start_l))\n                };\n            }\n            macro_rules! right {\n                () => {\n                    r.sub(usize::from(*start_r) + 1)\n                };\n            }\n\n            // Instead of swapping one pair at the time, it is more efficient to perform a cyclic\n            // permutation. This is not strictly equivalent to swapping, but produces a similar\n            // result using fewer memory operations.\n\n            // SAFETY: The use of `ptr::read` is valid because there is at least one element in\n            // both `offsets_l` and `offsets_r`, so `left!` is a valid pointer to read from.\n            //\n            // The uses of `left!` involve calls to `offset` on `l`, which points to the\n            // beginning of `v`. All the offsets pointed-to by `start_l` are at most `block_l`, so\n            // these `offset` calls are safe as all reads are within the block. The same argument\n            // applies for the uses of `right!`.\n            //\n            // The calls to `start_l.offset` are valid because there are at most `count-1` of them,\n            // plus the final one at the end of the unsafe block, where `count` is the minimum number\n            // of collected offsets in `offsets_l` and `offsets_r`, so there is no risk of there not\n            // being enough elements. The same reasoning applies to the calls to `start_r.offset`.\n            //\n            // The calls to `copy_nonoverlapping` are safe because `left!` and `right!` are guaranteed\n            // not to overlap, and are valid because of the reasoning above.\n            unsafe {\n                let tmp = ptr::read(left!());\n                ptr::copy_nonoverlapping(right!(), left!(), 1);\n\n                for _ in 1..count {\n                    start_l = start_l.add(1);\n                    ptr::copy_nonoverlapping(left!(), right!(), 1);\n                    start_r = start_r.add(1);\n                    ptr::copy_nonoverlapping(right!(), left!(), 1);\n                }\n\n                ptr::copy_nonoverlapping(&tmp, right!(), 1);\n                mem::forget(tmp);\n                start_l = start_l.add(1);\n                start_r = start_r.add(1);\n            }\n        }\n\n        if start_l == end_l {\n            // All out-of-order elements in the left block were moved. Move to the next block.\n\n            // block-width-guarantee\n            // SAFETY: if `!is_done` then the slice width is guaranteed to be at least `2*BLOCK` wide. There\n            // are at most `BLOCK` elements in `offsets_l` because of its size, so the `offset` operation is\n            // safe. Otherwise, the debug assertions in the `is_done` case guarantee that\n            // `width(l, r) == block_l + block_r`, namely, that the block sizes have been adjusted to account\n            // for the smaller number of remaining elements.\n            l = unsafe { l.add(block_l) };\n        }\n\n        if start_r == end_r {\n            // All out-of-order elements in the right block were moved. Move to the previous block.\n\n            // SAFETY: Same argument as [block-width-guarantee]. Either this is a full block `2*BLOCK`-wide,\n            // or `block_r` has been adjusted for the last handful of elements.\n            r = unsafe { r.sub(block_r) };\n        }\n\n        if is_done {\n            break;\n        }\n    }\n\n    // All that remains now is at most one block (either the left or the right) with out-of-order\n    // elements that need to be moved. Such remaining elements can be simply shifted to the end\n    // within their block.\n\n    if start_l < end_l {\n        // The left block remains.\n        // Move its remaining out-of-order elements to the far right.\n        debug_assert_eq!(width(l, r), block_l);\n        while start_l < end_l {\n            // remaining-elements-safety\n            // SAFETY: while the loop condition holds there are still elements in `offsets_l`, so it\n            // is safe to point `end_l` to the previous element.\n            //\n            // The `ptr::swap` is safe if both its arguments are valid for reads and writes:\n            //  - Per the debug assert above, the distance between `l` and `r` is `block_l`\n            //    elements, so there can be at most `block_l` remaining offsets between `start_l`\n            //    and `end_l`. This means `r` will be moved at most `block_l` steps back, which\n            //    makes the `r.offset` calls valid (at that point `l == r`).\n            //  - `offsets_l` contains valid offsets into `v` collected during the partitioning of\n            //    the last block, so the `l.offset` calls are valid.\n            unsafe {\n                end_l = end_l.sub(1);\n                ptr::swap(l.add(usize::from(*end_l)), r.sub(1));\n                r = r.sub(1);\n            }\n        }\n        width(v.as_mut_ptr(), r)\n    } else if start_r < end_r {\n        // The right block remains.\n        // Move its remaining out-of-order elements to the far left.\n        debug_assert_eq!(width(l, r), block_r);\n        while start_r < end_r {\n            // SAFETY: See the reasoning in [remaining-elements-safety].\n            unsafe {\n                end_r = end_r.sub(1);\n                ptr::swap(l, r.sub(usize::from(*end_r) + 1));\n                l = l.add(1);\n            }\n        }\n        width(v.as_mut_ptr(), l)\n    } else {\n        // Nothing else to do, we're done.\n        width(v.as_mut_ptr(), l)\n    }\n}\n\n/// Partitions `v` into elements smaller than `v[pivot]`, followed by elements greater than or\n/// equal to `v[pivot]`.\n///\n/// Returns a tuple of:\n///\n/// 1. Number of elements smaller than `v[pivot]`.\n/// 2. True if `v` was already partitioned.\nfn partition<T, F>(v: &mut [T], pivot: usize, is_less: &F) -> (usize, bool)\nwhere\n    F: Fn(&T, &T) -> bool,\n{\n    let (mid, was_partitioned) = {\n        // Place the pivot at the beginning of slice.\n        v.swap(0, pivot);\n        let (pivot, v) = v.split_at_mut(1);\n        let pivot = &mut pivot[0];\n\n        // Read the pivot into a stack-allocated variable for efficiency. If a following comparison\n        // operation panics, the pivot will be automatically written back into the slice.\n\n        // SAFETY: `pivot` is a reference to the first element of `v`, so `ptr::read` is safe.\n        let tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });\n        let _pivot_guard = InsertionHole {\n            src: &*tmp,\n            dest: pivot,\n        };\n        let pivot = &*tmp;\n\n        // Find the first pair of out-of-order elements.\n        let mut l = 0;\n        let mut r = v.len();\n\n        // SAFETY: The unsafety below involves indexing an array.\n        // For the first one: We already do the bounds checking here with `l < r`.\n        // For the second one: We initially have `l == 0` and `r == v.len()` and we checked that `l < r` at every indexing operation.\n        //                     From here we know that `r` must be at least `r == l` which was shown to be valid from the first one.\n        unsafe {\n            // Find the first element greater than or equal to the pivot.\n            while l < r && is_less(v.get_unchecked(l), pivot) {\n                l += 1;\n            }\n\n            // Find the last element smaller that the pivot.\n            while l < r && !is_less(v.get_unchecked(r - 1), pivot) {\n                r -= 1;\n            }\n        }\n\n        (\n            l + partition_in_blocks(&mut v[l..r], pivot, is_less),\n            l >= r,\n        )\n\n        // `_pivot_guard` goes out of scope and writes the pivot (which is a stack-allocated\n        // variable) back into the slice where it originally was. This step is critical in ensuring\n        // safety!\n    };\n\n    // Place the pivot between the two partitions.\n    v.swap(0, mid);\n\n    (mid, was_partitioned)\n}\n\n/// Partitions `v` into elements equal to `v[pivot]` followed by elements greater than `v[pivot]`.\n///\n/// Returns the number of elements equal to the pivot. It is assumed that `v` does not contain\n/// elements smaller than the pivot.\nfn partition_equal<T, F>(v: &mut [T], pivot: usize, is_less: &F) -> usize\nwhere\n    F: Fn(&T, &T) -> bool,\n{\n    // Place the pivot at the beginning of slice.\n    v.swap(0, pivot);\n    let (pivot, v) = v.split_at_mut(1);\n    let pivot = &mut pivot[0];\n\n    // Read the pivot into a stack-allocated variable for efficiency. If a following comparison\n    // operation panics, the pivot will be automatically written back into the slice.\n    // SAFETY: The pointer here is valid because it is obtained from a reference to a slice.\n    let tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });\n    let _pivot_guard = InsertionHole {\n        src: &*tmp,\n        dest: pivot,\n    };\n    let pivot = &*tmp;\n\n    let len = v.len();\n    if len == 0 {\n        return 0;\n    }\n\n    // Now partition the slice.\n    let mut l = 0;\n    let mut r = len;\n    loop {\n        // SAFETY: The unsafety below involves indexing an array.\n        // For the first one: We already do the bounds checking here with `l < r`.\n        // For the second one: We initially have `l == 0` and `r == v.len()` and we checked that `l < r` at every indexing operation.\n        //                     From here we know that `r` must be at least `r == l` which was shown to be valid from the first one.\n        unsafe {\n            // Find the first element greater than the pivot.\n            while l < r && !is_less(pivot, v.get_unchecked(l)) {\n                l += 1;\n            }\n\n            // Find the last element equal to the pivot.\n            loop {\n                r -= 1;\n                if l >= r || !is_less(pivot, v.get_unchecked(r)) {\n                    break;\n                }\n            }\n\n            // Are we done?\n            if l >= r {\n                break;\n            }\n\n            // Swap the found pair of out-of-order elements.\n            let ptr = v.as_mut_ptr();\n            ptr::swap(ptr.add(l), ptr.add(r));\n            l += 1;\n        }\n    }\n\n    // We found `l` elements equal to the pivot. Add 1 to account for the pivot itself.\n    l + 1\n\n    // `_pivot_guard` goes out of scope and writes the pivot (which is a stack-allocated variable)\n    // back into the slice where it originally was. This step is critical in ensuring safety!\n}\n\n/// Scatters some elements around in an attempt to break patterns that might cause imbalanced\n/// partitions in quicksort.\n#[cold]\nfn break_patterns<T>(v: &mut [T]) {\n    let len = v.len();\n    if len >= 8 {\n        let mut seed = len;\n        let mut gen_usize = || {\n            // Pseudorandom number generator from the \"Xorshift RNGs\" paper by George Marsaglia.\n            if usize::BITS <= 32 {\n                let mut r = seed as u32;\n                r ^= r << 13;\n                r ^= r >> 17;\n                r ^= r << 5;\n                seed = r as usize;\n                seed\n            } else {\n                let mut r = seed as u64;\n                r ^= r << 13;\n                r ^= r >> 7;\n                r ^= r << 17;\n                seed = r as usize;\n                seed\n            }\n        };\n\n        // Take random numbers modulo this number.\n        // The number fits into `usize` because `len` is not greater than `isize::MAX`.\n        let modulus = len.next_power_of_two();\n\n        // Some pivot candidates will be in the nearby of this index. Let's randomize them.\n        let pos = len / 4 * 2;\n\n        for i in 0..3 {\n            // Generate a random number modulo `len`. However, in order to avoid costly operations\n            // we first take it modulo a power of two, and then decrease by `len` until it fits\n            // into the range `[0, len - 1]`.\n            let mut other = gen_usize() & (modulus - 1);\n\n            // `other` is guaranteed to be less than `2 * len`.\n            if other >= len {\n                other -= len;\n            }\n\n            v.swap(pos - 1 + i, other);\n        }\n    }\n}\n\n/// Chooses a pivot in `v` and returns the index and `true` if the slice is likely already sorted.\n///\n/// Elements in `v` might be reordered in the process.\nfn choose_pivot<T, F>(v: &mut [T], is_less: &F) -> (usize, bool)\nwhere\n    F: Fn(&T, &T) -> bool,\n{\n    // Minimum length to choose the median-of-medians method.\n    // Shorter slices use the simple median-of-three method.\n    const SHORTEST_MEDIAN_OF_MEDIANS: usize = 50;\n    // Maximum number of swaps that can be performed in this function.\n    const MAX_SWAPS: usize = 4 * 3;\n\n    let len = v.len();\n\n    // Three indices near which we are going to choose a pivot.\n    #[allow(clippy::identity_op)]\n    let mut a = len / 4 * 1;\n    let mut b = len / 4 * 2;\n    let mut c = len / 4 * 3;\n\n    // Counts the total number of swaps we are about to perform while sorting indices.\n    let mut swaps = 0;\n\n    if len >= 8 {\n        // Swaps indices so that `v[a] <= v[b]`.\n        // SAFETY: `len >= 8` so there are at least two elements in the neighborhoods of\n        // `a`, `b` and `c`. This means the three calls to `sort_adjacent` result in\n        // corresponding calls to `sort3` with valid 3-item neighborhoods around each\n        // pointer, which in turn means the calls to `sort2` are done with valid\n        // references. Thus the `v.get_unchecked` calls are safe, as is the `ptr::swap`\n        // call.\n        let mut sort2 = |a: &mut usize, b: &mut usize| unsafe {\n            if is_less(v.get_unchecked(*b), v.get_unchecked(*a)) {\n                ptr::swap(a, b);\n                swaps += 1;\n            }\n        };\n\n        // Swaps indices so that `v[a] <= v[b] <= v[c]`.\n        let mut sort3 = |a: &mut usize, b: &mut usize, c: &mut usize| {\n            sort2(a, b);\n            sort2(b, c);\n            sort2(a, b);\n        };\n\n        if len >= SHORTEST_MEDIAN_OF_MEDIANS {\n            // Finds the median of `v[a - 1], v[a], v[a + 1]` and stores the index into `a`.\n            let mut sort_adjacent = |a: &mut usize| {\n                let tmp = *a;\n                sort3(&mut (tmp - 1), a, &mut (tmp + 1));\n            };\n\n            // Find medians in the neighborhoods of `a`, `b`, and `c`.\n            sort_adjacent(&mut a);\n            sort_adjacent(&mut b);\n            sort_adjacent(&mut c);\n        }\n\n        // Find the median among `a`, `b`, and `c`.\n        sort3(&mut a, &mut b, &mut c);\n    }\n\n    if swaps < MAX_SWAPS {\n        (b, swaps == 0)\n    } else {\n        // The maximum number of swaps was performed. Chances are the slice is descending or mostly\n        // descending, so reversing will probably help sort it faster.\n        v.reverse();\n        (len - 1 - b, true)\n    }\n}\n\n/// Sorts `v` recursively.\n///\n/// If the slice had a predecessor in the original array, it is specified as `pred`.\n///\n/// `limit` is the number of allowed imbalanced partitions before switching to `heapsort`. If zero,\n/// this function will immediately switch to heapsort.\nfn recurse<'a, T, F>(mut v: &'a mut [T], is_less: &F, mut pred: Option<&'a mut T>, mut limit: u32)\nwhere\n    T: Send,\n    F: Fn(&T, &T) -> bool + Sync,\n{\n    // Slices of up to this length get sorted using insertion sort.\n    const MAX_INSERTION: usize = 20;\n\n    // If both partitions are up to this length, we continue sequentially. This number is as small\n    // as possible but so that the overhead of Rayon's task scheduling is still negligible.\n    const MAX_SEQUENTIAL: usize = 2000;\n\n    // True if the last partitioning was reasonably balanced.\n    let mut was_balanced = true;\n    // True if the last partitioning didn't shuffle elements (the slice was already partitioned).\n    let mut was_partitioned = true;\n\n    loop {\n        let len = v.len();\n\n        // Very short slices get sorted using insertion sort.\n        if len <= MAX_INSERTION {\n            if len >= 2 {\n                insertion_sort_shift_left(v, 1, is_less);\n            }\n            return;\n        }\n\n        // If too many bad pivot choices were made, simply fall back to heapsort in order to\n        // guarantee `O(n * log(n))` worst-case.\n        if limit == 0 {\n            heapsort(v, is_less);\n            return;\n        }\n\n        // If the last partitioning was imbalanced, try breaking patterns in the slice by shuffling\n        // some elements around. Hopefully we'll choose a better pivot this time.\n        if !was_balanced {\n            break_patterns(v);\n            limit -= 1;\n        }\n\n        // Choose a pivot and try guessing whether the slice is already sorted.\n        let (pivot, likely_sorted) = choose_pivot(v, is_less);\n\n        // If the last partitioning was decently balanced and didn't shuffle elements, and if pivot\n        // selection predicts the slice is likely already sorted...\n        if was_balanced && was_partitioned && likely_sorted {\n            // Try identifying several out-of-order elements and shifting them to correct\n            // positions. If the slice ends up being completely sorted, we're done.\n            if partial_insertion_sort(v, is_less) {\n                return;\n            }\n        }\n\n        // If the chosen pivot is equal to the predecessor, then it's the smallest element in the\n        // slice. Partition the slice into elements equal to and elements greater than the pivot.\n        // This case is usually hit when the slice contains many duplicate elements.\n        if let Some(&mut ref p) = pred {\n            if !is_less(p, &v[pivot]) {\n                let mid = partition_equal(v, pivot, is_less);\n\n                // Continue sorting elements greater than the pivot.\n                v = &mut v[mid..];\n                continue;\n            }\n        }\n\n        // Partition the slice.\n        let (mid, was_p) = partition(v, pivot, is_less);\n        was_balanced = cmp::min(mid, len - mid) >= len / 8;\n        was_partitioned = was_p;\n\n        // Split the slice into `left`, `pivot`, and `right`.\n        let (left, right) = v.split_at_mut(mid);\n        let (pivot, right) = right.split_at_mut(1);\n        let pivot = &mut pivot[0];\n\n        if Ord::max(left.len(), right.len()) <= MAX_SEQUENTIAL {\n            // Recurse into the shorter side only in order to minimize the total number of recursive\n            // calls and consume less stack space. Then just continue with the longer side (this is\n            // akin to tail recursion).\n            if left.len() < right.len() {\n                recurse(left, is_less, pred, limit);\n                v = right;\n                pred = Some(pivot);\n            } else {\n                recurse(right, is_less, Some(pivot), limit);\n                v = left;\n            }\n        } else {\n            // Sort the left and right half in parallel.\n            rayon_core::join(\n                || recurse(left, is_less, pred, limit),\n                || recurse(right, is_less, Some(pivot), limit),\n            );\n            break;\n        }\n    }\n}\n\n/// Sorts `v` using pattern-defeating quicksort in parallel.\n///\n/// The algorithm is unstable, in-place, and *O*(*n* \\* log(*n*)) worst-case.\npub(super) fn par_quicksort<T, F>(v: &mut [T], is_less: F)\nwhere\n    T: Send,\n    F: Fn(&T, &T) -> bool + Sync,\n{\n    // Sorting has no meaningful behavior on zero-sized types.\n    if size_of::<T>() == 0 {\n        return;\n    }\n\n    // Limit the number of imbalanced partitions to `floor(log2(len)) + 1`.\n    let limit = usize::BITS - v.len().leading_zeros();\n\n    recurse(v, &is_less, None, limit);\n}\n\n/// Merges non-decreasing runs `v[..mid]` and `v[mid..]` using `buf` as temporary storage, and\n/// stores the result into `v[..]`.\n///\n/// # Safety\n///\n/// The two slices must be non-empty and `mid` must be in bounds. Buffer `buf` must be long enough\n/// to hold a copy of the shorter slice. Also, `T` must not be a zero-sized type.\nunsafe fn merge<T, F>(v: &mut [T], mid: usize, buf: *mut T, is_less: &F)\nwhere\n    F: Fn(&T, &T) -> bool,\n{\n    let len = v.len();\n    let v = v.as_mut_ptr();\n\n    // SAFETY: mid and len must be in-bounds of v.\n    let (v_mid, v_end) = unsafe { (v.add(mid), v.add(len)) };\n\n    // The merge process first copies the shorter run into `buf`. Then it traces the newly copied\n    // run and the longer run forwards (or backwards), comparing their next unconsumed elements and\n    // copying the lesser (or greater) one into `v`.\n    //\n    // As soon as the shorter run is fully consumed, the process is done. If the longer run gets\n    // consumed first, then we must copy whatever is left of the shorter run into the remaining\n    // hole in `v`.\n    //\n    // Intermediate state of the process is always tracked by `hole`, which serves two purposes:\n    // 1. Protects integrity of `v` from panics in `is_less`.\n    // 2. Fills the remaining hole in `v` if the longer run gets consumed first.\n    //\n    // Panic safety:\n    //\n    // If `is_less` panics at any point during the process, `hole` will get dropped and fill the\n    // hole in `v` with the unconsumed range in `buf`, thus ensuring that `v` still holds every\n    // object it initially held exactly once.\n    let mut hole;\n\n    if mid <= len - mid {\n        // The left run is shorter.\n\n        // SAFETY: buf must have enough capacity for `v[..mid]`.\n        unsafe {\n            ptr::copy_nonoverlapping(v, buf, mid);\n            hole = MergeHole {\n                start: buf,\n                end: buf.add(mid),\n                dest: v,\n            };\n        }\n\n        // Initially, these pointers point to the beginnings of their arrays.\n        let left = &mut hole.start;\n        let mut right = v_mid;\n        let out = &mut hole.dest;\n\n        while *left < hole.end && right < v_end {\n            // Consume the lesser side.\n            // If equal, prefer the left run to maintain stability.\n\n            // SAFETY: left and right must be valid and part of v same for out.\n            unsafe {\n                let is_l = is_less(&*right, &**left);\n                let to_copy = if is_l { right } else { *left };\n                ptr::copy_nonoverlapping(to_copy, *out, 1);\n                *out = out.add(1);\n                right = right.add(is_l as usize);\n                *left = left.add(!is_l as usize);\n            }\n        }\n    } else {\n        // The right run is shorter.\n\n        // SAFETY: buf must have enough capacity for `v[mid..]`.\n        unsafe {\n            ptr::copy_nonoverlapping(v_mid, buf, len - mid);\n            hole = MergeHole {\n                start: buf,\n                end: buf.add(len - mid),\n                dest: v_mid,\n            };\n        }\n\n        // Initially, these pointers point past the ends of their arrays.\n        let left = &mut hole.dest;\n        let right = &mut hole.end;\n        let mut out = v_end;\n\n        while v < *left && buf < *right {\n            // Consume the greater side.\n            // If equal, prefer the right run to maintain stability.\n\n            // SAFETY: left and right must be valid and part of v same for out.\n            unsafe {\n                let is_l = is_less(&*right.sub(1), &*left.sub(1));\n                *left = left.sub(is_l as usize);\n                *right = right.sub(!is_l as usize);\n                let to_copy = if is_l { *left } else { *right };\n                out = out.sub(1);\n                ptr::copy_nonoverlapping(to_copy, out, 1);\n            }\n        }\n    }\n    // Finally, `hole` gets dropped. If the shorter run was not fully consumed, whatever remains of\n    // it will now be copied into the hole in `v`.\n}\n\n// When dropped, copies the range `start..end` into `dest..`.\nstruct MergeHole<T> {\n    start: *mut T,\n    end: *mut T,\n    dest: *mut T,\n}\n\nimpl<T> Drop for MergeHole<T> {\n    fn drop(&mut self) {\n        // SAFETY: `T` is not a zero-sized type, and these are pointers into a slice's elements.\n        unsafe {\n            let len = self.end.offset_from(self.start) as usize;\n            ptr::copy_nonoverlapping(self.start, self.dest, len);\n        }\n    }\n}\n\n/// The result of merge sort.\n#[must_use]\n#[derive(Clone, Copy, PartialEq, Eq)]\nenum MergeSortResult {\n    /// The slice has already been sorted.\n    NonDescending,\n    /// The slice has been descending and therefore it was left intact.\n    Descending,\n    /// The slice was sorted.\n    Sorted,\n}\n\n/// This merge sort borrows some (but not all) ideas from TimSort, which used to be described in\n/// detail [here](https://github.com/python/cpython/blob/main/Objects/listsort.txt). However Python\n/// has switched to a Powersort based implementation.\n///\n/// The algorithm identifies strictly descending and non-descending subsequences, which are called\n/// natural runs. There is a stack of pending runs yet to be merged. Each newly found run is pushed\n/// onto the stack, and then some pairs of adjacent runs are merged until these two invariants are\n/// satisfied:\n///\n/// 1. for every `i` in `1..runs.len()`: `runs[i - 1].len > runs[i].len`\n/// 2. for every `i` in `2..runs.len()`: `runs[i - 2].len > runs[i - 1].len + runs[i].len`\n///\n/// The invariants ensure that the total running time is *O*(*n* \\* log(*n*)) worst-case.\n///\n/// # Safety\n///\n/// The argument `buf` is used as a temporary buffer and must hold at least `v.len() / 2`.\nunsafe fn merge_sort<T, CmpF>(v: &mut [T], buf_ptr: *mut T, is_less: &CmpF) -> MergeSortResult\nwhere\n    CmpF: Fn(&T, &T) -> bool,\n{\n    // The caller should have already checked that.\n    debug_assert_ne!(size_of::<T>(), 0);\n\n    let len = v.len();\n\n    let mut runs = Vec::new();\n\n    let mut end = 0;\n    let mut start = 0;\n\n    // Scan forward. Memory pre-fetching prefers forward scanning vs backwards scanning, and the\n    // code-gen is usually better. For the most sensitive types such as integers, these are merged\n    // bidirectionally at once. So there is no benefit in scanning backwards.\n    while end < len {\n        let (streak_end, was_reversed) = find_streak(&v[start..], is_less);\n        end += streak_end;\n        if start == 0 && end == len {\n            return if was_reversed {\n                MergeSortResult::Descending\n            } else {\n                MergeSortResult::NonDescending\n            };\n        }\n        if was_reversed {\n            v[start..end].reverse();\n        }\n\n        // Insert some more elements into the run if it's too short. Insertion sort is faster than\n        // merge sort on short sequences, so this significantly improves performance.\n        end = provide_sorted_batch(v, start, end, is_less);\n\n        // Push this run onto the stack.\n        runs.push(TimSortRun {\n            start,\n            len: end - start,\n        });\n        start = end;\n\n        // Merge some pairs of adjacent runs to satisfy the invariants.\n        while let Some(r) = collapse(runs.as_slice(), len) {\n            let left = runs[r];\n            let right = runs[r + 1];\n            let merge_slice = &mut v[left.start..right.start + right.len];\n            // SAFETY: `buf_ptr` must hold enough capacity for the shorter of the two sides, and\n            // neither side may be on length 0.\n            unsafe {\n                merge(merge_slice, left.len, buf_ptr, is_less);\n            }\n            runs[r + 1] = TimSortRun {\n                start: left.start,\n                len: left.len + right.len,\n            };\n            runs.remove(r);\n        }\n    }\n\n    // Finally, exactly one run must remain in the stack.\n    debug_assert!(runs.len() == 1 && runs[0].start == 0 && runs[0].len == len);\n\n    // The original order of the slice was neither non-descending nor descending.\n    return MergeSortResult::Sorted;\n\n    // Examines the stack of runs and identifies the next pair of runs to merge. More specifically,\n    // if `Some(r)` is returned, that means `runs[r]` and `runs[r + 1]` must be merged next. If the\n    // algorithm should continue building a new run instead, `None` is returned.\n    //\n    // TimSort is infamous for its buggy implementations, as described here:\n    // http://envisage-project.eu/timsort-specification-and-verification/\n    //\n    // The gist of the story is: we must enforce the invariants on the top four runs on the stack.\n    // Enforcing them on just top three is not sufficient to ensure that the invariants will still\n    // hold for *all* runs in the stack.\n    //\n    // This function correctly checks invariants for the top four runs. Additionally, if the top\n    // run starts at index 0, it will always demand a merge operation until the stack is fully\n    // collapsed, in order to complete the sort.\n    #[inline]\n    fn collapse(runs: &[TimSortRun], stop: usize) -> Option<usize> {\n        let n = runs.len();\n        if n >= 2\n            && (runs[n - 1].start + runs[n - 1].len == stop\n                || runs[n - 2].len <= runs[n - 1].len\n                || (n >= 3 && runs[n - 3].len <= runs[n - 2].len + runs[n - 1].len)\n                || (n >= 4 && runs[n - 4].len <= runs[n - 3].len + runs[n - 2].len))\n        {\n            if n >= 3 && runs[n - 3].len < runs[n - 1].len {\n                Some(n - 3)\n            } else {\n                Some(n - 2)\n            }\n        } else {\n            None\n        }\n    }\n}\n\n/// Internal type used by merge_sort.\n#[derive(Clone, Copy, Debug)]\nstruct TimSortRun {\n    len: usize,\n    start: usize,\n}\n\n/// Takes a range as denoted by start and end, that is already sorted and extends it to the right if\n/// necessary with sorts optimized for smaller ranges such as insertion sort.\nfn provide_sorted_batch<T, F>(v: &mut [T], start: usize, mut end: usize, is_less: &F) -> usize\nwhere\n    F: Fn(&T, &T) -> bool,\n{\n    let len = v.len();\n    assert!(end >= start && end <= len);\n\n    // This value is a balance between least comparisons and best performance, as\n    // influenced by for example cache locality.\n    const MIN_INSERTION_RUN: usize = 10;\n\n    // Insert some more elements into the run if it's too short. Insertion sort is faster than\n    // merge sort on short sequences, so this significantly improves performance.\n    let start_end_diff = end - start;\n\n    if start_end_diff < MIN_INSERTION_RUN && end < len {\n        // v[start_found..end] are elements that are already sorted in the input. We want to extend\n        // the sorted region to the left, so we push up MIN_INSERTION_RUN - 1 to the right. Which is\n        // more efficient that trying to push those already sorted elements to the left.\n        end = cmp::min(start + MIN_INSERTION_RUN, len);\n        let presorted_start = cmp::max(start_end_diff, 1);\n\n        insertion_sort_shift_left(&mut v[start..end], presorted_start, is_less);\n    }\n\n    end\n}\n\n/// Finds a streak of presorted elements starting at the beginning of the slice. Returns the first\n/// value that is not part of said streak, and a bool denoting whether the streak was reversed.\n/// Streaks can be increasing or decreasing.\nfn find_streak<T, F>(v: &[T], is_less: &F) -> (usize, bool)\nwhere\n    F: Fn(&T, &T) -> bool,\n{\n    let len = v.len();\n\n    if len < 2 {\n        return (len, false);\n    }\n\n    let mut end = 2;\n\n    // SAFETY: See below specific.\n    unsafe {\n        // SAFETY: We checked that len >= 2, so 0 and 1 are valid indices.\n        let assume_reverse = is_less(v.get_unchecked(1), v.get_unchecked(0));\n\n        // SAFETY: We know end >= 2 and check end < len.\n        // From that follows that accessing v at end and end - 1 is safe.\n        if assume_reverse {\n            while end < len && is_less(v.get_unchecked(end), v.get_unchecked(end - 1)) {\n                end += 1;\n            }\n\n            (end, true)\n        } else {\n            while end < len && !is_less(v.get_unchecked(end), v.get_unchecked(end - 1)) {\n                end += 1;\n            }\n            (end, false)\n        }\n    }\n}\n\n////////////////////////////////////////////////////////////////////////////\n// Everything above this line is copied from `core::slice::sort` (with very minor tweaks).\n// Everything below this line is custom parallelization for rayon.\n////////////////////////////////////////////////////////////////////////////\n\n/// Splits two sorted slices so that they can be merged in parallel.\n///\n/// Returns two indices `(a, b)` so that slices `left[..a]` and `right[..b]` come before\n/// `left[a..]` and `right[b..]`.\nfn split_for_merge<T, F>(left: &[T], right: &[T], is_less: &F) -> (usize, usize)\nwhere\n    F: Fn(&T, &T) -> bool,\n{\n    let left_len = left.len();\n    let right_len = right.len();\n\n    if left_len >= right_len {\n        let left_mid = left_len / 2;\n\n        // Find the first element in `right` that is greater than or equal to `left[left_mid]`.\n        let mut a = 0;\n        let mut b = right_len;\n        while a < b {\n            let m = a + (b - a) / 2;\n            if is_less(&right[m], &left[left_mid]) {\n                a = m + 1;\n            } else {\n                b = m;\n            }\n        }\n\n        (left_mid, a)\n    } else {\n        let right_mid = right_len / 2;\n\n        // Find the first element in `left` that is greater than `right[right_mid]`.\n        let mut a = 0;\n        let mut b = left_len;\n        while a < b {\n            let m = a + (b - a) / 2;\n            if is_less(&right[right_mid], &left[m]) {\n                b = m;\n            } else {\n                a = m + 1;\n            }\n        }\n\n        (a, right_mid)\n    }\n}\n\n/// Merges slices `left` and `right` in parallel and stores the result into `dest`.\n///\n/// # Safety\n///\n/// The `dest` pointer must have enough space to store the result.\n///\n/// Even if `is_less` panics at any point during the merge process, this function will fully copy\n/// all elements from `left` and `right` into `dest` (not necessarily in sorted order).\nunsafe fn par_merge<T, F>(left: &mut [T], right: &mut [T], dest: *mut T, is_less: &F)\nwhere\n    T: Send,\n    F: Fn(&T, &T) -> bool + Sync,\n{\n    // Slices whose lengths sum up to this value are merged sequentially. This number is slightly\n    // larger than `CHUNK_LENGTH`, and the reason is that merging is faster than merge sorting, so\n    // merging needs a bit coarser granularity in order to hide the overhead of Rayon's task\n    // scheduling.\n    const MAX_SEQUENTIAL: usize = 5000;\n\n    let left_len = left.len();\n    let right_len = right.len();\n\n    // Intermediate state of the merge process, which serves two purposes:\n    // 1. Protects integrity of `dest` from panics in `is_less`.\n    // 2. Copies the remaining elements as soon as one of the two sides is exhausted.\n    //\n    // Panic safety:\n    //\n    // If `is_less` panics at any point during the merge process, `s` will get dropped and copy the\n    // remaining parts of `left` and `right` into `dest`.\n    let mut s = State {\n        left_start: left.as_mut_ptr(),\n        left_end: left.as_mut_ptr().add(left_len),\n        right_start: right.as_mut_ptr(),\n        right_end: right.as_mut_ptr().add(right_len),\n        dest,\n    };\n\n    if left_len == 0 || right_len == 0 || left_len + right_len < MAX_SEQUENTIAL {\n        while s.left_start < s.left_end && s.right_start < s.right_end {\n            // Consume the lesser side.\n            // If equal, prefer the left run to maintain stability.\n            let is_l = is_less(&*s.right_start, &*s.left_start);\n            let to_copy = if is_l { s.right_start } else { s.left_start };\n            ptr::copy_nonoverlapping(to_copy, s.dest, 1);\n            s.dest = s.dest.add(1);\n            s.right_start = s.right_start.add(is_l as usize);\n            s.left_start = s.left_start.add(!is_l as usize);\n        }\n    } else {\n        // Function `split_for_merge` might panic. If that happens, `s` will get destructed and copy\n        // the whole `left` and `right` into `dest`.\n        let (left_mid, right_mid) = split_for_merge(left, right, is_less);\n        let (left_l, left_r) = left.split_at_mut(left_mid);\n        let (right_l, right_r) = right.split_at_mut(right_mid);\n\n        // Prevent the destructor of `s` from running. Rayon will ensure that both calls to\n        // `par_merge` happen. If one of the two calls panics, they will ensure that elements still\n        // get copied into `dest_left` and `dest_right``.\n        mem::forget(s);\n\n        // Wrap pointers in SendPtr so that they can be sent to another thread\n        // See the documentation of SendPtr for a full explanation\n        let dest_l = SendPtr(dest);\n        let dest_r = SendPtr(dest.add(left_l.len() + right_l.len()));\n        rayon_core::join(\n            move || par_merge(left_l, right_l, dest_l.get(), is_less),\n            move || par_merge(left_r, right_r, dest_r.get(), is_less),\n        );\n    }\n    // Finally, `s` gets dropped if we used sequential merge, thus copying the remaining elements\n    // all at once.\n\n    // When dropped, copies arrays `left_start..left_end` and `right_start..right_end` into `dest`,\n    // in that order.\n    struct State<T> {\n        left_start: *mut T,\n        left_end: *mut T,\n        right_start: *mut T,\n        right_end: *mut T,\n        dest: *mut T,\n    }\n\n    impl<T> Drop for State<T> {\n        fn drop(&mut self) {\n            // Copy array `left`, followed by `right`.\n            unsafe {\n                let left_len = self.left_end.offset_from(self.left_start) as usize;\n                ptr::copy_nonoverlapping(self.left_start, self.dest, left_len);\n                self.dest = self.dest.add(left_len);\n\n                let right_len = self.right_end.offset_from(self.right_start) as usize;\n                ptr::copy_nonoverlapping(self.right_start, self.dest, right_len);\n            }\n        }\n    }\n}\n\n/// Recursively merges pre-sorted chunks inside `v`.\n///\n/// Chunks of `v` are stored in `chunks` as intervals (inclusive left and exclusive right bound).\n/// Argument `buf` is an auxiliary buffer that will be used during the procedure.\n/// If `into_buf` is true, the result will be stored into `buf`, otherwise it will be in `v`.\n///\n/// # Safety\n///\n/// The number of chunks must be positive and they must be adjacent: the right bound of each chunk\n/// must equal the left bound of the following chunk.\n///\n/// The buffer must be at least as long as `v`.\nunsafe fn merge_recurse<T, F>(\n    v: *mut T,\n    buf: *mut T,\n    chunks: &[(usize, usize)],\n    into_buf: bool,\n    is_less: &F,\n) where\n    T: Send,\n    F: Fn(&T, &T) -> bool + Sync,\n{\n    let len = chunks.len();\n    debug_assert!(len > 0);\n\n    // Base case of the algorithm.\n    // If only one chunk is remaining, there's no more work to split and merge.\n    if len == 1 {\n        if into_buf {\n            // Copy the chunk from `v` into `buf`.\n            let (start, end) = chunks[0];\n            let src = v.add(start);\n            let dest = buf.add(start);\n            ptr::copy_nonoverlapping(src, dest, end - start);\n        }\n        return;\n    }\n\n    // Split the chunks into two halves.\n    let (start, _) = chunks[0];\n    let (mid, _) = chunks[len / 2];\n    let (_, end) = chunks[len - 1];\n    let (left, right) = chunks.split_at(len / 2);\n\n    // After recursive calls finish we'll have to merge chunks `(start, mid)` and `(mid, end)` from\n    // `src` into `dest`. If the current invocation has to store the result into `buf`, we'll\n    // merge chunks from `v` into `buf`, and vice versa.\n    //\n    // Recursive calls flip `into_buf` at each level of recursion. More concretely, `par_merge`\n    // merges chunks from `buf` into `v` at the first level, from `v` into `buf` at the second\n    // level etc.\n    let (src, dest) = if into_buf { (v, buf) } else { (buf, v) };\n\n    // Panic safety:\n    //\n    // If `is_less` panics at any point during the recursive calls, the destructor of `guard` will\n    // be executed, thus copying everything from `src` into `dest`. This way we ensure that all\n    // chunks are in fact copied into `dest`, even if the merge process doesn't finish.\n    let guard = MergeHole {\n        start: src.add(start),\n        end: src.add(end),\n        dest: dest.add(start),\n    };\n\n    // Wrap pointers in SendPtr so that they can be sent to another thread\n    // See the documentation of SendPtr for a full explanation\n    let v = SendPtr(v);\n    let buf = SendPtr(buf);\n    rayon_core::join(\n        move || merge_recurse(v.get(), buf.get(), left, !into_buf, is_less),\n        move || merge_recurse(v.get(), buf.get(), right, !into_buf, is_less),\n    );\n\n    // Everything went all right - recursive calls didn't panic.\n    // Forget the guard in order to prevent its destructor from running.\n    mem::forget(guard);\n\n    // Merge chunks `(start, mid)` and `(mid, end)` from `src` into `dest`.\n    let src_left = slice::from_raw_parts_mut(src.add(start), mid - start);\n    let src_right = slice::from_raw_parts_mut(src.add(mid), end - mid);\n    par_merge(src_left, src_right, dest.add(start), is_less);\n}\n\n/// Sorts `v` using merge sort in parallel.\n///\n/// The algorithm is stable, allocates memory, and `O(n log n)` worst-case.\n/// The allocated temporary buffer is of the same length as is `v`.\npub(super) fn par_mergesort<T, F>(v: &mut [T], is_less: F)\nwhere\n    T: Send,\n    F: Fn(&T, &T) -> bool + Sync,\n{\n    // Slices of up to this length get sorted using insertion sort in order to avoid the cost of\n    // buffer allocation.\n    const MAX_INSERTION: usize = 20;\n\n    // The length of initial chunks. This number is as small as possible but so that the overhead\n    // of Rayon's task scheduling is still negligible.\n    const CHUNK_LENGTH: usize = 2000;\n\n    // Sorting has no meaningful behavior on zero-sized types.\n    if size_of::<T>() == 0 {\n        return;\n    }\n\n    let len = v.len();\n\n    // Short slices get sorted in-place via insertion sort to avoid allocations.\n    if len <= MAX_INSERTION {\n        if len >= 2 {\n            insertion_sort_shift_left(v, 1, &is_less);\n        }\n        return;\n    }\n\n    // Allocate a buffer to use as scratch memory. We keep the length 0 so we can keep in it\n    // shallow copies of the contents of `v` without risking the dtors running on copies if\n    // `is_less` panics.\n    let mut buf = Vec::<T>::with_capacity(len);\n    let buf = buf.as_mut_ptr();\n\n    // If the slice is not longer than one chunk would be, do sequential merge sort and return.\n    if len <= CHUNK_LENGTH {\n        let res = unsafe { merge_sort(v, buf, &is_less) };\n        if res == MergeSortResult::Descending {\n            v.reverse();\n        }\n        return;\n    }\n\n    // Split the slice into chunks and merge sort them in parallel.\n    // However, descending chunks will not be sorted - they will be simply left intact.\n    let mut iter = {\n        // Wrap pointer in SendPtr so that it can be sent to another thread\n        // See the documentation of SendPtr for a full explanation\n        let buf = SendPtr(buf);\n        let is_less = &is_less;\n\n        v.par_chunks_mut(CHUNK_LENGTH)\n            .with_max_len(1)\n            .enumerate()\n            .map(move |(i, chunk)| {\n                let l = CHUNK_LENGTH * i;\n                let r = l + chunk.len();\n                unsafe {\n                    let buf = buf.get().add(l);\n                    (l, r, merge_sort(chunk, buf, is_less))\n                }\n            })\n            .collect::<Vec<_>>()\n            .into_iter()\n            .peekable()\n    };\n\n    // Now attempt to concatenate adjacent chunks that were left intact.\n    let mut chunks = Vec::with_capacity(iter.len());\n\n    while let Some((a, mut b, res)) = iter.next() {\n        // If this chunk was not modified by the sort procedure...\n        if res != MergeSortResult::Sorted {\n            while let Some(&(x, y, r)) = iter.peek() {\n                // If the following chunk is of the same type and can be concatenated...\n                if r == res && (r == MergeSortResult::Descending) == is_less(&v[x], &v[x - 1]) {\n                    // Concatenate them.\n                    b = y;\n                    iter.next();\n                } else {\n                    break;\n                }\n            }\n        }\n\n        // Descending chunks must be reversed.\n        if res == MergeSortResult::Descending {\n            v[a..b].reverse();\n        }\n\n        chunks.push((a, b));\n    }\n\n    // All chunks are properly sorted.\n    // Now we just have to merge them together.\n    unsafe {\n        merge_recurse(v.as_mut_ptr(), buf, &chunks, false, &is_less);\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::heapsort;\n    use super::split_for_merge;\n    use rand::distr::Uniform;\n    use rand::{rng, Rng};\n\n    #[test]\n    fn test_heapsort() {\n        let rng = &mut rng();\n\n        for len in (0..25).chain(500..501) {\n            for &modulus in &[5, 10, 100] {\n                let dist = Uniform::new(0, modulus).unwrap();\n                for _ in 0..100 {\n                    let v: Vec<i32> = rng.sample_iter(&dist).take(len).collect();\n\n                    // Test heapsort using `<` operator.\n                    let mut tmp = v.clone();\n                    heapsort(&mut tmp, |a, b| a < b);\n                    assert!(tmp.windows(2).all(|w| w[0] <= w[1]));\n\n                    // Test heapsort using `>` operator.\n                    let mut tmp = v.clone();\n                    heapsort(&mut tmp, |a, b| a > b);\n                    assert!(tmp.windows(2).all(|w| w[0] >= w[1]));\n                }\n            }\n        }\n\n        // Sort using a completely random comparison function.\n        // This will reorder the elements *somehow*, but won't panic.\n        let mut v: Vec<_> = (0..100).collect();\n        heapsort(&mut v, |_, _| rand::rng().random());\n        heapsort(&mut v, |a, b| a < b);\n\n        for (i, &entry) in v.iter().enumerate() {\n            assert_eq!(entry, i);\n        }\n    }\n\n    #[test]\n    fn test_split_for_merge() {\n        fn check(left: &[u32], right: &[u32]) {\n            let (l, r) = split_for_merge(left, right, &|&a, &b| a < b);\n            assert!(left[..l]\n                .iter()\n                .all(|&x| right[r..].iter().all(|&y| x <= y)));\n            assert!(right[..r].iter().all(|&x| left[l..].iter().all(|&y| x < y)));\n        }\n\n        check(&[1, 2, 2, 2, 2, 3], &[1, 2, 2, 2, 2, 3]);\n        check(&[1, 2, 2, 2, 2, 3], &[]);\n        check(&[], &[1, 2, 2, 2, 2, 3]);\n\n        let rng = &mut rng();\n\n        for _ in 0..100 {\n            let limit: u32 = rng.random_range(1..21);\n            let left_len: usize = rng.random_range(0..20);\n            let right_len: usize = rng.random_range(0..20);\n\n            let mut left = rng\n                .sample_iter(&Uniform::new(0, limit).unwrap())\n                .take(left_len)\n                .collect::<Vec<_>>();\n            let mut right = rng\n                .sample_iter(&Uniform::new(0, limit).unwrap())\n                .take(right_len)\n                .collect::<Vec<_>>();\n\n            left.sort();\n            right.sort();\n            check(&left, &right);\n        }\n    }\n}\n"
  },
  {
    "path": "src/slice/test.rs",
    "content": "#![cfg(test)]\n\nuse crate::prelude::*;\nuse rand::distr::Uniform;\nuse rand::seq::IndexedRandom;\nuse rand::{rng, Rng};\nuse std::cmp::Ordering::{Equal, Greater, Less};\nuse std::sync::atomic::{AtomicUsize, Ordering::Relaxed};\n\nmacro_rules! sort {\n    ($f:ident, $name:ident) => {\n        #[test]\n        fn $name() {\n            let rng = &mut rng();\n\n            for len in (0..25).chain(500..501) {\n                for &modulus in &[5, 10, 100] {\n                    let dist = Uniform::new(0, modulus).unwrap();\n                    for _ in 0..100 {\n                        let v: Vec<i32> = rng.sample_iter(&dist).take(len).collect();\n\n                        // Test sort using `<` operator.\n                        let mut tmp = v.clone();\n                        tmp.$f(|a, b| a.cmp(b));\n                        assert!(tmp.windows(2).all(|w| w[0] <= w[1]));\n\n                        // Test sort using `>` operator.\n                        let mut tmp = v.clone();\n                        tmp.$f(|a, b| b.cmp(a));\n                        assert!(tmp.windows(2).all(|w| w[0] >= w[1]));\n                    }\n                }\n            }\n\n            // Test sort with many duplicates.\n            for &len in &[1_000, 10_000, 100_000] {\n                for &modulus in &[5, 10, 100, 10_000] {\n                    let dist = Uniform::new(0, modulus).unwrap();\n                    let mut v: Vec<i32> = rng.sample_iter(&dist).take(len).collect();\n\n                    v.$f(|a, b| a.cmp(b));\n                    assert!(v.windows(2).all(|w| w[0] <= w[1]));\n                }\n            }\n\n            // Test sort with many pre-sorted runs.\n            for &len in &[1_000, 10_000, 100_000] {\n                let len_dist = Uniform::new(0, len).unwrap();\n                for &modulus in &[5, 10, 1000, 50_000] {\n                    let dist = Uniform::new(0, modulus).unwrap();\n                    let mut v: Vec<i32> = rng.sample_iter(&dist).take(len).collect();\n\n                    v.sort();\n                    v.reverse();\n\n                    for _ in 0..5 {\n                        let a = rng.sample(&len_dist);\n                        let b = rng.sample(&len_dist);\n                        if a < b {\n                            v[a..b].reverse();\n                        } else {\n                            v.swap(a, b);\n                        }\n                    }\n\n                    v.$f(|a, b| a.cmp(b));\n                    assert!(v.windows(2).all(|w| w[0] <= w[1]));\n                }\n            }\n\n            // Sort using a completely random comparison function.\n            // This will reorder the elements *somehow*, but won't panic.\n            let mut v: Vec<_> = (0..100).collect();\n            v.$f(|_, _| *[Less, Equal, Greater].choose(&mut rand::rng()).unwrap());\n            v.$f(|a, b| a.cmp(b));\n            for i in 0..v.len() {\n                assert_eq!(v[i], i);\n            }\n\n            // Should not panic.\n            [0i32; 0].$f(|a, b| a.cmp(b));\n            [(); 10].$f(|a, b| a.cmp(b));\n            [(); 100].$f(|a, b| a.cmp(b));\n\n            let mut v = [0xDEAD_BEEFu64];\n            v.$f(|a, b| a.cmp(b));\n            assert!(v == [0xDEAD_BEEF]);\n        }\n    };\n}\n\nsort!(par_sort_by, test_par_sort);\nsort!(par_sort_unstable_by, test_par_sort_unstable);\n\n#[test]\nfn test_par_sort_stability() {\n    for len in (2..25).chain(500..510).chain(50_000..50_010) {\n        for _ in 0..10 {\n            let mut counts = [0; 10];\n\n            // Create a vector like [(6, 1), (5, 1), (6, 2), ...],\n            // where the first item of each tuple is random, but\n            // the second item represents which occurrence of that\n            // number this element is, i.e. the second elements\n            // will occur in sorted order.\n            let mut rng = rng();\n            let mut v: Vec<_> = (0..len)\n                .map(|_| {\n                    let n: usize = rng.random_range(0..10);\n                    counts[n] += 1;\n                    (n, counts[n])\n                })\n                .collect();\n\n            // Only sort on the first element, so an unstable sort\n            // may mix up the counts.\n            v.par_sort_by(|&(a, _), &(b, _)| a.cmp(&b));\n\n            // This comparison includes the count (the second item\n            // of the tuple), so elements with equal first items\n            // will need to be ordered with increasing\n            // counts... i.e. exactly asserting that this sort is\n            // stable.\n            assert!(v.windows(2).all(|w| w[0] <= w[1]));\n        }\n    }\n}\n\n#[test]\nfn test_par_chunks_exact_remainder() {\n    let v: &[i32] = &[0, 1, 2, 3, 4];\n    let c = v.par_chunks_exact(2);\n    assert_eq!(c.remainder(), &[4]);\n    assert_eq!(c.len(), 2);\n}\n\n#[test]\nfn test_par_chunks_exact_mut_remainder() {\n    let v: &mut [i32] = &mut [0, 1, 2, 3, 4];\n    let mut c = v.par_chunks_exact_mut(2);\n    assert_eq!(c.remainder(), &[4]);\n    assert_eq!(c.len(), 2);\n    assert_eq!(c.into_remainder(), &[4]);\n\n    let mut c = v.par_chunks_exact_mut(2);\n    assert_eq!(c.take_remainder(), &[4]);\n    assert_eq!(c.take_remainder(), &[]);\n    assert_eq!(c.len(), 2);\n}\n\n#[test]\nfn test_par_rchunks_exact_remainder() {\n    let v: &[i32] = &[0, 1, 2, 3, 4];\n    let c = v.par_rchunks_exact(2);\n    assert_eq!(c.remainder(), &[0]);\n    assert_eq!(c.len(), 2);\n}\n\n#[test]\nfn test_par_rchunks_exact_mut_remainder() {\n    let v: &mut [i32] = &mut [0, 1, 2, 3, 4];\n    let mut c = v.par_rchunks_exact_mut(2);\n    assert_eq!(c.remainder(), &[0]);\n    assert_eq!(c.len(), 2);\n    assert_eq!(c.into_remainder(), &[0]);\n\n    let mut c = v.par_rchunks_exact_mut(2);\n    assert_eq!(c.take_remainder(), &[0]);\n    assert_eq!(c.take_remainder(), &[]);\n    assert_eq!(c.len(), 2);\n}\n\n#[test]\nfn slice_chunk_by() {\n    let v: Vec<_> = (0..1000).collect();\n    assert_eq!(v[..0].par_chunk_by(|_, _| todo!()).count(), 0);\n    assert_eq!(v[..1].par_chunk_by(|_, _| todo!()).count(), 1);\n    assert_eq!(v[..2].par_chunk_by(|_, _| true).count(), 1);\n    assert_eq!(v[..2].par_chunk_by(|_, _| false).count(), 2);\n\n    let count = AtomicUsize::new(0);\n    let par: Vec<_> = v\n        .par_chunk_by(|x, y| {\n            count.fetch_add(1, Relaxed);\n            (x % 10 < 3) == (y % 10 < 3)\n        })\n        .collect();\n    assert_eq!(count.into_inner(), v.len() - 1);\n\n    let seq: Vec<_> = v.chunk_by(|x, y| (x % 10 < 3) == (y % 10 < 3)).collect();\n    assert_eq!(par, seq);\n}\n\n#[test]\nfn slice_chunk_by_mut() {\n    let mut v: Vec<_> = (0..1000).collect();\n    assert_eq!(v[..0].par_chunk_by_mut(|_, _| todo!()).count(), 0);\n    assert_eq!(v[..1].par_chunk_by_mut(|_, _| todo!()).count(), 1);\n    assert_eq!(v[..2].par_chunk_by_mut(|_, _| true).count(), 1);\n    assert_eq!(v[..2].par_chunk_by_mut(|_, _| false).count(), 2);\n\n    let mut v2 = v.clone();\n    let count = AtomicUsize::new(0);\n    let par: Vec<_> = v\n        .par_chunk_by_mut(|x, y| {\n            count.fetch_add(1, Relaxed);\n            (x % 10 < 3) == (y % 10 < 3)\n        })\n        .collect();\n    assert_eq!(count.into_inner(), v2.len() - 1);\n\n    let seq: Vec<_> = v2\n        .chunk_by_mut(|x, y| (x % 10 < 3) == (y % 10 < 3))\n        .collect();\n    assert_eq!(par, seq);\n}\n"
  },
  {
    "path": "src/split_producer.rs",
    "content": "//! Common splitter for strings and slices\n//!\n//! This module is private, so these items are effectively `pub(super)`\n\nuse crate::iter::plumbing::{Folder, UnindexedProducer};\n\n/// Common producer for splitting on a predicate.\npub(super) struct SplitProducer<'p, P, V, const INCL: bool = false> {\n    data: V,\n    separator: &'p P,\n\n    /// Marks the endpoint beyond which we've already found no separators.\n    tail: usize,\n}\n\npub(super) type SplitInclusiveProducer<'p, P, V> = SplitProducer<'p, P, V, true>;\n\n/// Helper trait so `&str`, `&[T]`, and `&mut [T]` can share `SplitProducer`.\npub(super) trait Fissile<P>: Sized {\n    fn length(&self) -> usize;\n    fn midpoint(&self, end: usize) -> usize;\n    fn find(&self, separator: &P, start: usize, end: usize) -> Option<usize>;\n    fn rfind(&self, separator: &P, end: usize) -> Option<usize>;\n    fn split_once<const INCL: bool>(self, index: usize) -> (Self, Self);\n    fn fold_splits<F, const INCL: bool>(self, separator: &P, folder: F, skip_last: bool) -> F\n    where\n        F: Folder<Self>,\n        Self: Send;\n}\n\nimpl<'p, P, V> SplitProducer<'p, P, V>\nwhere\n    V: Fissile<P> + Send,\n{\n    pub(super) fn new(data: V, separator: &'p P) -> Self {\n        SplitProducer {\n            tail: data.length(),\n            data,\n            separator,\n        }\n    }\n}\n\nimpl<'p, P, V> SplitInclusiveProducer<'p, P, V>\nwhere\n    V: Fissile<P> + Send,\n{\n    pub(super) fn new_incl(data: V, separator: &'p P) -> Self {\n        SplitProducer {\n            tail: data.length(),\n            data,\n            separator,\n        }\n    }\n}\n\nimpl<'p, P, V, const INCL: bool> SplitProducer<'p, P, V, INCL>\nwhere\n    V: Fissile<P> + Send,\n{\n    /// Common `fold_with` implementation, integrating `SplitTerminator`'s\n    /// need to sometimes skip its final empty item.\n    pub(super) fn fold_with<F>(self, folder: F, skip_last: bool) -> F\n    where\n        F: Folder<V>,\n    {\n        let SplitProducer {\n            data,\n            separator,\n            tail,\n        } = self;\n\n        if tail == data.length() {\n            // No tail section, so just let `fold_splits` handle it.\n            data.fold_splits::<F, INCL>(separator, folder, skip_last)\n        } else if let Some(index) = data.rfind(separator, tail) {\n            // We found the last separator to complete the tail, so\n            // end with that slice after `fold_splits` finds the rest.\n            let (left, right) = data.split_once::<INCL>(index);\n            let folder = left.fold_splits::<F, INCL>(separator, folder, false);\n            if skip_last || folder.full() {\n                folder\n            } else {\n                folder.consume(right)\n            }\n        } else {\n            // We know there are no separators at all.  Return our whole data.\n            if skip_last {\n                folder\n            } else {\n                folder.consume(data)\n            }\n        }\n    }\n}\n\nimpl<'p, P, V, const INCL: bool> UnindexedProducer for SplitProducer<'p, P, V, INCL>\nwhere\n    V: Fissile<P> + Send,\n    P: Sync,\n{\n    type Item = V;\n\n    fn split(self) -> (Self, Option<Self>) {\n        // Look forward for the separator, and failing that look backward.\n        let mid = self.data.midpoint(self.tail);\n        let index = match self.data.find(self.separator, mid, self.tail) {\n            Some(i) => Some(mid + i),\n            None => self.data.rfind(self.separator, mid),\n        };\n\n        if let Some(index) = index {\n            let len = self.data.length();\n            let (left, right) = self.data.split_once::<INCL>(index);\n\n            let (left_tail, right_tail) = if index < mid {\n                // If we scanned backwards to find the separator, everything in\n                // the right side is exhausted, with no separators left to find.\n                (index, 0)\n            } else {\n                let right_index = len - right.length();\n                (mid, self.tail - right_index)\n            };\n\n            // Create the left split before the separator.\n            let left = SplitProducer {\n                data: left,\n                tail: left_tail,\n                ..self\n            };\n\n            // Create the right split following the separator.\n            let right = SplitProducer {\n                data: right,\n                tail: right_tail,\n                ..self\n            };\n\n            (left, Some(right))\n        } else {\n            // The search is exhausted, no more separators...\n            (SplitProducer { tail: 0, ..self }, None)\n        }\n    }\n\n    fn fold_with<F>(self, folder: F) -> F\n    where\n        F: Folder<Self::Item>,\n    {\n        self.fold_with(folder, false)\n    }\n}\n"
  },
  {
    "path": "src/str.rs",
    "content": "//! Parallel iterator types for [strings]\n//!\n//! You will rarely need to interact with this module directly unless you need\n//! to name one of the iterator types.\n//!\n//! Note: [`ParallelString::par_split()`] and [`par_split_terminator()`]\n//! reference a `Pattern` trait which is not visible outside this crate.\n//! This trait is intentionally kept private, for use only by Rayon itself.\n//! It is implemented for `char`, `&[char]`, `[char; N]`, `&[char; N]`,\n//! and any function or closure `F: Fn(char) -> bool + Sync + Send`.\n//!\n//! [`par_split_terminator()`]: ParallelString::par_split_terminator()\n//! [strings]: std::str\n\nuse crate::iter::plumbing::*;\nuse crate::iter::*;\nuse crate::split_producer::*;\n\n/// Test if a byte is the start of a UTF-8 character.\n/// (extracted from `str::is_char_boundary`)\n#[inline]\nfn is_char_boundary(b: u8) -> bool {\n    // This is bit magic equivalent to: b < 128 || b >= 192\n    (b as i8) >= -0x40\n}\n\n/// Find the index of a character boundary near the midpoint.\n#[inline]\nfn find_char_midpoint(chars: &str) -> usize {\n    let mid = chars.len() / 2;\n\n    // We want to split near the midpoint, but we need to find an actual\n    // character boundary.  So we look at the raw bytes, first scanning\n    // forward from the midpoint for a boundary, then trying backward.\n    // TODO (MSRV 1.91): use `str::ceil_char_boundary`, else `floor_...`.\n    let (left, right) = chars.as_bytes().split_at(mid);\n    match right.iter().copied().position(is_char_boundary) {\n        Some(i) => mid + i,\n        None => left\n            .iter()\n            .copied()\n            .rposition(is_char_boundary)\n            .unwrap_or(0),\n    }\n}\n\n/// Try to split a string near the midpoint.\n#[inline]\nfn split(chars: &str) -> Option<(&str, &str)> {\n    let index = find_char_midpoint(chars);\n    if index > 0 {\n        Some(chars.split_at(index))\n    } else {\n        None\n    }\n}\n\n/// Parallel extensions for strings.\npub trait ParallelString {\n    /// Returns a plain string slice, which is used to implement the rest of\n    /// the parallel methods.\n    fn as_parallel_string(&self) -> &str;\n\n    /// Returns a parallel iterator over the characters of a string.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let max = \"hello\".par_chars().max_by_key(|c| *c as i32);\n    /// assert_eq!(Some('o'), max);\n    /// ```\n    fn par_chars(&self) -> Chars<'_> {\n        Chars {\n            chars: self.as_parallel_string(),\n        }\n    }\n\n    /// Returns a parallel iterator over the characters of a string, with their positions.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let min = \"hello\".par_char_indices().min_by_key(|&(_i, c)| c as i32);\n    /// assert_eq!(Some((1, 'e')), min);\n    /// ```\n    fn par_char_indices(&self) -> CharIndices<'_> {\n        CharIndices {\n            chars: self.as_parallel_string(),\n        }\n    }\n\n    /// Returns a parallel iterator over the bytes of a string.\n    ///\n    /// Note that multi-byte sequences (for code points greater than `U+007F`)\n    /// are produced as separate items, but will not be split across threads.\n    /// If you would prefer an indexed iterator without that guarantee, consider\n    /// `string.as_bytes().par_iter().copied()` instead.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let max = \"hello\".par_bytes().max();\n    /// assert_eq!(Some(b'o'), max);\n    /// ```\n    fn par_bytes(&self) -> Bytes<'_> {\n        Bytes {\n            chars: self.as_parallel_string(),\n        }\n    }\n\n    /// Returns a parallel iterator over a string encoded as UTF-16.\n    ///\n    /// Note that surrogate pairs (for code points greater than `U+FFFF`) are\n    /// produced as separate items, but will not be split across threads.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    ///\n    /// let max = \"hello\".par_encode_utf16().max();\n    /// assert_eq!(Some(b'o' as u16), max);\n    ///\n    /// let text = \"Zażółć gęślą jaźń\";\n    /// let utf8_len = text.len();\n    /// let utf16_len = text.par_encode_utf16().count();\n    /// assert!(utf16_len <= utf8_len);\n    /// ```\n    fn par_encode_utf16(&self) -> EncodeUtf16<'_> {\n        EncodeUtf16 {\n            chars: self.as_parallel_string(),\n        }\n    }\n\n    /// Returns a parallel iterator over substrings separated by a\n    /// given character or predicate, similar to `str::split`.\n    ///\n    /// Note: the `Pattern` trait is private, for use only by Rayon itself.\n    /// It is implemented for `char`, `&[char]`, `[char; N]`, `&[char; N]`,\n    /// and any function or closure `F: Fn(char) -> bool + Sync + Send`.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let total = \"1, 2, buckle, 3, 4, door\"\n    ///    .par_split(',')\n    ///    .filter_map(|s| s.trim().parse::<i32>().ok())\n    ///    .sum();\n    /// assert_eq!(10, total);\n    /// ```\n    fn par_split<P: Pattern>(&self, separator: P) -> Split<'_, P> {\n        Split::new(self.as_parallel_string(), separator)\n    }\n\n    /// Returns a parallel iterator over substrings separated by a\n    /// given character or predicate, keeping the matched part as a terminator\n    /// of the substring similar to `str::split_inclusive`.\n    ///\n    /// Note: the `Pattern` trait is private, for use only by Rayon itself.\n    /// It is implemented for `char`, `&[char]`, `[char; N]`, `&[char; N]`,\n    /// and any function or closure `F: Fn(char) -> bool + Sync + Send`.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let lines: Vec<_> = \"Mary had a little lamb\\nlittle lamb\\nlittle lamb.\"\n    ///    .par_split_inclusive('\\n')\n    ///    .collect();\n    /// assert_eq!(lines, [\"Mary had a little lamb\\n\", \"little lamb\\n\", \"little lamb.\"]);\n    /// ```\n    fn par_split_inclusive<P: Pattern>(&self, separator: P) -> SplitInclusive<'_, P> {\n        SplitInclusive::new(self.as_parallel_string(), separator)\n    }\n\n    /// Returns a parallel iterator over substrings terminated by a\n    /// given character or predicate, similar to `str::split_terminator`.\n    /// It's equivalent to `par_split`, except it doesn't produce an empty\n    /// substring after a trailing terminator.\n    ///\n    /// Note: the `Pattern` trait is private, for use only by Rayon itself.\n    /// It is implemented for `char`, `&[char]`, `[char; N]`, `&[char; N]`,\n    /// and any function or closure `F: Fn(char) -> bool + Sync + Send`.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let parts: Vec<_> = \"((1 + 3) * 2)\"\n    ///     .par_split_terminator(|c| c == '(' || c == ')')\n    ///     .collect();\n    /// assert_eq!(vec![\"\", \"\", \"1 + 3\", \" * 2\"], parts);\n    /// ```\n    fn par_split_terminator<P: Pattern>(&self, terminator: P) -> SplitTerminator<'_, P> {\n        SplitTerminator::new(self.as_parallel_string(), terminator)\n    }\n\n    /// Returns a parallel iterator over the lines of a string, ending with an\n    /// optional carriage return and with a newline (`\\r\\n` or just `\\n`).\n    /// The final line ending is optional, and line endings are not included in\n    /// the output strings.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let lengths: Vec<_> = \"hello world\\nfizbuzz\"\n    ///     .par_lines()\n    ///     .map(|l| l.len())\n    ///     .collect();\n    /// assert_eq!(vec![11, 7], lengths);\n    /// ```\n    fn par_lines(&self) -> Lines<'_> {\n        Lines(self.as_parallel_string())\n    }\n\n    /// Returns a parallel iterator over the sub-slices of a string that are\n    /// separated by any amount of whitespace.\n    ///\n    /// As with `str::split_whitespace`, 'whitespace' is defined according to\n    /// the terms of the Unicode Derived Core Property `White_Space`.\n    /// If you only want to split on ASCII whitespace instead, use\n    /// [`par_split_ascii_whitespace`][`ParallelString::par_split_ascii_whitespace`].\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let longest = \"which is the longest word?\"\n    ///     .par_split_whitespace()\n    ///     .max_by_key(|word| word.len());\n    /// assert_eq!(Some(\"longest\"), longest);\n    /// ```\n    ///\n    /// All kinds of whitespace are considered:\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let words: Vec<&str> = \" Mary   had\\ta\\u{2009}little  \\n\\t lamb\"\n    ///     .par_split_whitespace()\n    ///     .collect();\n    /// assert_eq!(words, [\"Mary\", \"had\", \"a\", \"little\", \"lamb\"]);\n    /// ```\n    ///\n    /// If the string is empty or all whitespace, the iterator yields no string slices:\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// assert_eq!(\"\".par_split_whitespace().count(), 0);\n    /// assert_eq!(\"   \".par_split_whitespace().count(), 0);\n    /// ```\n    fn par_split_whitespace(&self) -> SplitWhitespace<'_> {\n        SplitWhitespace(self.as_parallel_string())\n    }\n\n    /// Returns a parallel iterator over the sub-slices of a string that are\n    /// separated by any amount of ASCII whitespace.\n    ///\n    /// To split by Unicode `White_Space` instead, use\n    /// [`par_split_whitespace`][`ParallelString::par_split_whitespace`].\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let longest = \"which is the longest word?\"\n    ///     .par_split_ascii_whitespace()\n    ///     .max_by_key(|word| word.len());\n    /// assert_eq!(Some(\"longest\"), longest);\n    /// ```\n    ///\n    /// All kinds of ASCII whitespace are considered, but not Unicode `White_Space`:\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let words: Vec<&str> = \" Mary   had\\ta\\u{2009}little  \\n\\t lamb\"\n    ///     .par_split_ascii_whitespace()\n    ///     .collect();\n    /// assert_eq!(words, [\"Mary\", \"had\", \"a\\u{2009}little\", \"lamb\"]);\n    /// ```\n    ///\n    /// If the string is empty or all ASCII whitespace, the iterator yields no string slices:\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// assert_eq!(\"\".par_split_whitespace().count(), 0);\n    /// assert_eq!(\"   \".par_split_whitespace().count(), 0);\n    /// ```\n    fn par_split_ascii_whitespace(&self) -> SplitAsciiWhitespace<'_> {\n        SplitAsciiWhitespace(self.as_parallel_string())\n    }\n\n    /// Returns a parallel iterator over substrings that match a\n    /// given character or predicate, similar to `str::matches`.\n    ///\n    /// Note: the `Pattern` trait is private, for use only by Rayon itself.\n    /// It is implemented for `char`, `&[char]`, `[char; N]`, `&[char; N]`,\n    /// and any function or closure `F: Fn(char) -> bool + Sync + Send`.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let total = \"1, 2, buckle, 3, 4, door\"\n    ///    .par_matches(char::is_numeric)\n    ///    .map(|s| s.parse::<i32>().expect(\"digit\"))\n    ///    .sum();\n    /// assert_eq!(10, total);\n    /// ```\n    fn par_matches<P: Pattern>(&self, pattern: P) -> Matches<'_, P> {\n        Matches {\n            chars: self.as_parallel_string(),\n            pattern,\n        }\n    }\n\n    /// Returns a parallel iterator over substrings that match a given character\n    /// or predicate, with their positions, similar to `str::match_indices`.\n    ///\n    /// Note: the `Pattern` trait is private, for use only by Rayon itself.\n    /// It is implemented for `char`, `&[char]`, `[char; N]`, `&[char; N]`,\n    /// and any function or closure `F: Fn(char) -> bool + Sync + Send`.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use rayon::prelude::*;\n    /// let digits: Vec<_> = \"1, 2, buckle, 3, 4, door\"\n    ///    .par_match_indices(char::is_numeric)\n    ///    .collect();\n    /// assert_eq!(digits, vec![(0, \"1\"), (3, \"2\"), (14, \"3\"), (17, \"4\")]);\n    /// ```\n    fn par_match_indices<P: Pattern>(&self, pattern: P) -> MatchIndices<'_, P> {\n        MatchIndices {\n            chars: self.as_parallel_string(),\n            pattern,\n        }\n    }\n}\n\nimpl ParallelString for str {\n    #[inline]\n    fn as_parallel_string(&self) -> &str {\n        self\n    }\n}\n\n// /////////////////////////////////////////////////////////////////////////\n\n/// We hide the `Pattern` trait in a private module, as its API is not meant\n/// for general consumption.  If we could have privacy on trait items, then it\n/// would be nicer to have its basic existence and implementors public while\n/// keeping all of the methods private.\nmod private {\n    use crate::iter::plumbing::Folder;\n\n    /// Pattern-matching trait for `ParallelString`, somewhat like a mix of\n    /// `std::str::pattern::{Pattern, Searcher}`.\n    ///\n    /// Implementing this trait is not permitted outside of `rayon`.\n    pub trait Pattern: Sized + Sync + Send {\n        private_decl! {}\n        fn find_in(&self, haystack: &str) -> Option<usize>;\n        fn rfind_in(&self, haystack: &str) -> Option<usize>;\n        fn is_suffix_of(&self, haystack: &str) -> bool;\n        fn fold_splits<'ch, F>(&self, haystack: &'ch str, folder: F, skip_last: bool) -> F\n        where\n            F: Folder<&'ch str>;\n        fn fold_inclusive_splits<'ch, F>(&self, haystack: &'ch str, folder: F) -> F\n        where\n            F: Folder<&'ch str>;\n        fn fold_matches<'ch, F>(&self, haystack: &'ch str, folder: F) -> F\n        where\n            F: Folder<&'ch str>;\n        fn fold_match_indices<'ch, F>(&self, haystack: &'ch str, folder: F, base: usize) -> F\n        where\n            F: Folder<(usize, &'ch str)>;\n    }\n}\nuse self::private::Pattern;\n\n#[inline]\nfn offset<T>(base: usize) -> impl Fn((usize, T)) -> (usize, T) {\n    move |(i, x)| (base + i, x)\n}\n\nmacro_rules! impl_pattern {\n    (&$self:ident => $pattern:expr) => {\n        private_impl! {}\n\n        #[inline]\n        fn find_in(&$self, chars: &str) -> Option<usize> {\n            chars.find($pattern)\n        }\n\n        #[inline]\n        fn rfind_in(&$self, chars: &str) -> Option<usize> {\n            chars.rfind($pattern)\n        }\n\n        #[inline]\n        fn is_suffix_of(&$self, chars: &str) -> bool {\n            chars.ends_with($pattern)\n        }\n\n        fn fold_splits<'ch, F>(&$self, chars: &'ch str, folder: F, skip_last: bool) -> F\n        where\n            F: Folder<&'ch str>,\n        {\n            let mut split = chars.split($pattern);\n            if skip_last {\n                split.next_back();\n            }\n            folder.consume_iter(split)\n        }\n\n        fn fold_inclusive_splits<'ch, F>(&$self, chars: &'ch str, folder: F) -> F\n        where\n            F: Folder<&'ch str>,\n        {\n            folder.consume_iter(chars.split_inclusive($pattern))\n        }\n\n        fn fold_matches<'ch, F>(&$self, chars: &'ch str, folder: F) -> F\n        where\n            F: Folder<&'ch str>,\n        {\n            folder.consume_iter(chars.matches($pattern))\n        }\n\n        fn fold_match_indices<'ch, F>(&$self, chars: &'ch str, folder: F, base: usize) -> F\n        where\n            F: Folder<(usize, &'ch str)>,\n        {\n            folder.consume_iter(chars.match_indices($pattern).map(offset(base)))\n        }\n    }\n}\n\nimpl Pattern for char {\n    impl_pattern!(&self => *self);\n}\n\nimpl Pattern for &[char] {\n    impl_pattern!(&self => *self);\n}\n\nimpl<const N: usize> Pattern for [char; N] {\n    impl_pattern!(&self => *self);\n}\n\nimpl<const N: usize> Pattern for &[char; N] {\n    impl_pattern!(&self => *self);\n}\n\nimpl<FN: Sync + Send + Fn(char) -> bool> Pattern for FN {\n    impl_pattern!(&self => self);\n}\n\n// /////////////////////////////////////////////////////////////////////////\n\n/// Parallel iterator over the characters of a string\n#[derive(Debug, Clone)]\npub struct Chars<'ch> {\n    chars: &'ch str,\n}\n\nstruct CharsProducer<'ch> {\n    chars: &'ch str,\n}\n\nimpl<'ch> ParallelIterator for Chars<'ch> {\n    type Item = char;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge_unindexed(CharsProducer { chars: self.chars }, consumer)\n    }\n}\n\nimpl<'ch> UnindexedProducer for CharsProducer<'ch> {\n    type Item = char;\n\n    fn split(self) -> (Self, Option<Self>) {\n        match split(self.chars) {\n            Some((left, right)) => (\n                CharsProducer { chars: left },\n                Some(CharsProducer { chars: right }),\n            ),\n            None => (self, None),\n        }\n    }\n\n    fn fold_with<F>(self, folder: F) -> F\n    where\n        F: Folder<Self::Item>,\n    {\n        folder.consume_iter(self.chars.chars())\n    }\n}\n\n// /////////////////////////////////////////////////////////////////////////\n\n/// Parallel iterator over the characters of a string, with their positions\n#[derive(Debug, Clone)]\npub struct CharIndices<'ch> {\n    chars: &'ch str,\n}\n\nstruct CharIndicesProducer<'ch> {\n    index: usize,\n    chars: &'ch str,\n}\n\nimpl<'ch> ParallelIterator for CharIndices<'ch> {\n    type Item = (usize, char);\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let producer = CharIndicesProducer {\n            index: 0,\n            chars: self.chars,\n        };\n        bridge_unindexed(producer, consumer)\n    }\n}\n\nimpl<'ch> UnindexedProducer for CharIndicesProducer<'ch> {\n    type Item = (usize, char);\n\n    fn split(self) -> (Self, Option<Self>) {\n        match split(self.chars) {\n            Some((left, right)) => (\n                CharIndicesProducer {\n                    chars: left,\n                    ..self\n                },\n                Some(CharIndicesProducer {\n                    chars: right,\n                    index: self.index + left.len(),\n                }),\n            ),\n            None => (self, None),\n        }\n    }\n\n    fn fold_with<F>(self, folder: F) -> F\n    where\n        F: Folder<Self::Item>,\n    {\n        let base = self.index;\n        folder.consume_iter(self.chars.char_indices().map(offset(base)))\n    }\n}\n\n// /////////////////////////////////////////////////////////////////////////\n\n/// Parallel iterator over the bytes of a string\n#[derive(Debug, Clone)]\npub struct Bytes<'ch> {\n    chars: &'ch str,\n}\n\nstruct BytesProducer<'ch> {\n    chars: &'ch str,\n}\n\nimpl<'ch> ParallelIterator for Bytes<'ch> {\n    type Item = u8;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge_unindexed(BytesProducer { chars: self.chars }, consumer)\n    }\n}\n\nimpl<'ch> UnindexedProducer for BytesProducer<'ch> {\n    type Item = u8;\n\n    fn split(self) -> (Self, Option<Self>) {\n        match split(self.chars) {\n            Some((left, right)) => (\n                BytesProducer { chars: left },\n                Some(BytesProducer { chars: right }),\n            ),\n            None => (self, None),\n        }\n    }\n\n    fn fold_with<F>(self, folder: F) -> F\n    where\n        F: Folder<Self::Item>,\n    {\n        folder.consume_iter(self.chars.bytes())\n    }\n}\n\n// /////////////////////////////////////////////////////////////////////////\n\n/// Parallel iterator over a string encoded as UTF-16\n#[derive(Debug, Clone)]\npub struct EncodeUtf16<'ch> {\n    chars: &'ch str,\n}\n\nstruct EncodeUtf16Producer<'ch> {\n    chars: &'ch str,\n}\n\nimpl<'ch> ParallelIterator for EncodeUtf16<'ch> {\n    type Item = u16;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge_unindexed(EncodeUtf16Producer { chars: self.chars }, consumer)\n    }\n}\n\nimpl<'ch> UnindexedProducer for EncodeUtf16Producer<'ch> {\n    type Item = u16;\n\n    fn split(self) -> (Self, Option<Self>) {\n        match split(self.chars) {\n            Some((left, right)) => (\n                EncodeUtf16Producer { chars: left },\n                Some(EncodeUtf16Producer { chars: right }),\n            ),\n            None => (self, None),\n        }\n    }\n\n    fn fold_with<F>(self, folder: F) -> F\n    where\n        F: Folder<Self::Item>,\n    {\n        folder.consume_iter(self.chars.encode_utf16())\n    }\n}\n\n// /////////////////////////////////////////////////////////////////////////\n\n/// Parallel iterator over substrings separated by a pattern\n#[derive(Debug, Clone)]\npub struct Split<'ch, P: Pattern> {\n    chars: &'ch str,\n    separator: P,\n}\n\nimpl<'ch, P: Pattern> Split<'ch, P> {\n    fn new(chars: &'ch str, separator: P) -> Self {\n        Split { chars, separator }\n    }\n}\n\nimpl<'ch, P: Pattern> ParallelIterator for Split<'ch, P> {\n    type Item = &'ch str;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let producer = SplitProducer::new(self.chars, &self.separator);\n        bridge_unindexed(producer, consumer)\n    }\n}\n\n/// Implement support for `SplitProducer`.\nimpl<P: Pattern> Fissile<P> for &str {\n    fn length(&self) -> usize {\n        self.len()\n    }\n\n    fn midpoint(&self, end: usize) -> usize {\n        // First find a suitable UTF-8 boundary.\n        find_char_midpoint(&self[..end])\n    }\n\n    fn find(&self, separator: &P, start: usize, end: usize) -> Option<usize> {\n        separator.find_in(&self[start..end])\n    }\n\n    fn rfind(&self, separator: &P, end: usize) -> Option<usize> {\n        separator.rfind_in(&self[..end])\n    }\n\n    fn split_once<const INCL: bool>(self, index: usize) -> (Self, Self) {\n        if INCL {\n            // include the separator in the left side\n            let separator = self[index..].chars().next().unwrap();\n            self.split_at(index + separator.len_utf8())\n        } else {\n            let (left, right) = self.split_at(index);\n            let mut right_iter = right.chars();\n            right_iter.next(); // skip the separator\n            (left, right_iter.as_str())\n        }\n    }\n\n    fn fold_splits<F, const INCL: bool>(self, separator: &P, folder: F, skip_last: bool) -> F\n    where\n        F: Folder<Self>,\n    {\n        if INCL {\n            debug_assert!(!skip_last);\n            separator.fold_inclusive_splits(self, folder)\n        } else {\n            separator.fold_splits(self, folder, skip_last)\n        }\n    }\n}\n\n// /////////////////////////////////////////////////////////////////////////\n\n/// Parallel iterator over substrings separated by a pattern\n#[derive(Debug, Clone)]\npub struct SplitInclusive<'ch, P: Pattern> {\n    chars: &'ch str,\n    separator: P,\n}\n\nimpl<'ch, P: Pattern> SplitInclusive<'ch, P> {\n    fn new(chars: &'ch str, separator: P) -> Self {\n        SplitInclusive { chars, separator }\n    }\n}\n\nimpl<'ch, P: Pattern> ParallelIterator for SplitInclusive<'ch, P> {\n    type Item = &'ch str;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let producer = SplitInclusiveProducer::new_incl(self.chars, &self.separator);\n        bridge_unindexed(producer, consumer)\n    }\n}\n\n// /////////////////////////////////////////////////////////////////////////\n\n/// Parallel iterator over substrings separated by a terminator pattern\n#[derive(Debug, Clone)]\npub struct SplitTerminator<'ch, P: Pattern> {\n    chars: &'ch str,\n    terminator: P,\n}\n\nstruct SplitTerminatorProducer<'ch, 'sep, P: Pattern> {\n    splitter: SplitProducer<'sep, P, &'ch str>,\n    skip_last: bool,\n}\n\nimpl<'ch, P: Pattern> SplitTerminator<'ch, P> {\n    fn new(chars: &'ch str, terminator: P) -> Self {\n        SplitTerminator { chars, terminator }\n    }\n}\n\nimpl<'ch, 'sep, P: Pattern + 'sep> SplitTerminatorProducer<'ch, 'sep, P> {\n    fn new(chars: &'ch str, terminator: &'sep P) -> Self {\n        SplitTerminatorProducer {\n            splitter: SplitProducer::new(chars, terminator),\n            skip_last: chars.is_empty() || terminator.is_suffix_of(chars),\n        }\n    }\n}\n\nimpl<'ch, P: Pattern> ParallelIterator for SplitTerminator<'ch, P> {\n    type Item = &'ch str;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let producer = SplitTerminatorProducer::new(self.chars, &self.terminator);\n        bridge_unindexed(producer, consumer)\n    }\n}\n\nimpl<'ch, 'sep, P: Pattern + 'sep> UnindexedProducer for SplitTerminatorProducer<'ch, 'sep, P> {\n    type Item = &'ch str;\n\n    fn split(mut self) -> (Self, Option<Self>) {\n        let (left, right) = self.splitter.split();\n        self.splitter = left;\n        let right = right.map(|right| {\n            let skip_last = self.skip_last;\n            self.skip_last = false;\n            SplitTerminatorProducer {\n                splitter: right,\n                skip_last,\n            }\n        });\n        (self, right)\n    }\n\n    fn fold_with<F>(self, folder: F) -> F\n    where\n        F: Folder<Self::Item>,\n    {\n        self.splitter.fold_with(folder, self.skip_last)\n    }\n}\n\n// /////////////////////////////////////////////////////////////////////////\n\n/// Parallel iterator over lines in a string\n#[derive(Debug, Clone)]\npub struct Lines<'ch>(&'ch str);\n\n#[inline]\nfn no_carriage_return(line: &str) -> &str {\n    line.strip_suffix('\\r').unwrap_or(line)\n}\n\nimpl<'ch> ParallelIterator for Lines<'ch> {\n    type Item = &'ch str;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        self.0\n            .par_split_terminator('\\n')\n            .map(no_carriage_return)\n            .drive_unindexed(consumer)\n    }\n}\n\n// /////////////////////////////////////////////////////////////////////////\n\n/// Parallel iterator over substrings separated by whitespace\n#[derive(Debug, Clone)]\npub struct SplitWhitespace<'ch>(&'ch str);\n\n#[inline]\nfn not_empty(s: &&str) -> bool {\n    !s.is_empty()\n}\n\nimpl<'ch> ParallelIterator for SplitWhitespace<'ch> {\n    type Item = &'ch str;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        self.0\n            .par_split(char::is_whitespace)\n            .filter(not_empty)\n            .drive_unindexed(consumer)\n    }\n}\n\n// /////////////////////////////////////////////////////////////////////////\n\n/// Parallel iterator over substrings separated by ASCII whitespace\n#[derive(Debug, Clone)]\npub struct SplitAsciiWhitespace<'ch>(&'ch str);\n\n#[inline]\nfn is_ascii_whitespace(c: char) -> bool {\n    c.is_ascii_whitespace()\n}\n\nimpl<'ch> ParallelIterator for SplitAsciiWhitespace<'ch> {\n    type Item = &'ch str;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        self.0\n            .par_split(is_ascii_whitespace)\n            .filter(not_empty)\n            .drive_unindexed(consumer)\n    }\n}\n\n// /////////////////////////////////////////////////////////////////////////\n\n/// Parallel iterator over substrings that match a pattern\n#[derive(Debug, Clone)]\npub struct Matches<'ch, P: Pattern> {\n    chars: &'ch str,\n    pattern: P,\n}\n\nstruct MatchesProducer<'ch, 'pat, P: Pattern> {\n    chars: &'ch str,\n    pattern: &'pat P,\n}\n\nimpl<'ch, P: Pattern> ParallelIterator for Matches<'ch, P> {\n    type Item = &'ch str;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let producer = MatchesProducer {\n            chars: self.chars,\n            pattern: &self.pattern,\n        };\n        bridge_unindexed(producer, consumer)\n    }\n}\n\nimpl<'ch, 'pat, P: Pattern> UnindexedProducer for MatchesProducer<'ch, 'pat, P> {\n    type Item = &'ch str;\n\n    fn split(self) -> (Self, Option<Self>) {\n        match split(self.chars) {\n            Some((left, right)) => (\n                MatchesProducer {\n                    chars: left,\n                    ..self\n                },\n                Some(MatchesProducer {\n                    chars: right,\n                    ..self\n                }),\n            ),\n            None => (self, None),\n        }\n    }\n\n    fn fold_with<F>(self, folder: F) -> F\n    where\n        F: Folder<Self::Item>,\n    {\n        self.pattern.fold_matches(self.chars, folder)\n    }\n}\n\n// /////////////////////////////////////////////////////////////////////////\n\n/// Parallel iterator over substrings that match a pattern, with their positions\n#[derive(Debug, Clone)]\npub struct MatchIndices<'ch, P: Pattern> {\n    chars: &'ch str,\n    pattern: P,\n}\n\nstruct MatchIndicesProducer<'ch, 'pat, P: Pattern> {\n    index: usize,\n    chars: &'ch str,\n    pattern: &'pat P,\n}\n\nimpl<'ch, P: Pattern> ParallelIterator for MatchIndices<'ch, P> {\n    type Item = (usize, &'ch str);\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        let producer = MatchIndicesProducer {\n            index: 0,\n            chars: self.chars,\n            pattern: &self.pattern,\n        };\n        bridge_unindexed(producer, consumer)\n    }\n}\n\nimpl<'ch, 'pat, P: Pattern> UnindexedProducer for MatchIndicesProducer<'ch, 'pat, P> {\n    type Item = (usize, &'ch str);\n\n    fn split(self) -> (Self, Option<Self>) {\n        match split(self.chars) {\n            Some((left, right)) => (\n                MatchIndicesProducer {\n                    chars: left,\n                    ..self\n                },\n                Some(MatchIndicesProducer {\n                    chars: right,\n                    index: self.index + left.len(),\n                    ..self\n                }),\n            ),\n            None => (self, None),\n        }\n    }\n\n    fn fold_with<F>(self, folder: F) -> F\n    where\n        F: Folder<Self::Item>,\n    {\n        self.pattern\n            .fold_match_indices(self.chars, folder, self.index)\n    }\n}\n"
  },
  {
    "path": "src/string.rs",
    "content": "//! This module contains the parallel iterator types for owned strings\n//! (`String`). You will rarely need to interact with it directly\n//! unless you have need to name one of the iterator types.\n\nuse crate::iter::plumbing::*;\nuse crate::math::simplify_range;\nuse crate::prelude::*;\nuse std::ops::{Range, RangeBounds};\n\nimpl<'a> ParallelDrainRange<usize> for &'a mut String {\n    type Iter = Drain<'a>;\n    type Item = char;\n\n    fn par_drain<R: RangeBounds<usize>>(self, range: R) -> Self::Iter {\n        Drain {\n            range: simplify_range(range, self.len()),\n            string: self,\n        }\n    }\n}\n\n/// Draining parallel iterator that moves a range of characters out of a string,\n/// but keeps the total capacity.\n#[derive(Debug)]\npub struct Drain<'a> {\n    string: &'a mut String,\n    range: Range<usize>,\n}\n\nimpl<'a> ParallelIterator for Drain<'a> {\n    type Item = char;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        self.string[self.range.clone()]\n            .par_chars()\n            .drive_unindexed(consumer)\n    }\n}\n\nimpl<'a> Drop for Drain<'a> {\n    fn drop(&mut self) {\n        // Remove the drained range.\n        self.string.drain(self.range.clone());\n    }\n}\n"
  },
  {
    "path": "src/vec.rs",
    "content": "//! Parallel iterator types for [vectors] (`Vec<T>`)\n//!\n//! You will rarely need to interact with this module directly unless you need\n//! to name one of the iterator types.\n//!\n//! [vectors]: mod@std::vec\n\nuse crate::iter::plumbing::*;\nuse crate::iter::*;\nuse crate::math::simplify_range;\nuse crate::slice::{Iter, IterMut};\nuse std::iter;\nuse std::mem;\nuse std::ops::{Range, RangeBounds};\nuse std::ptr;\nuse std::slice;\n\nimpl<'data, T: Sync + 'data> IntoParallelIterator for &'data Vec<T> {\n    type Item = &'data T;\n    type Iter = Iter<'data, T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        <&[T]>::into_par_iter(self)\n    }\n}\n\nimpl<'data, T: Send + 'data> IntoParallelIterator for &'data mut Vec<T> {\n    type Item = &'data mut T;\n    type Iter = IterMut<'data, T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        <&mut [T]>::into_par_iter(self)\n    }\n}\n\n/// Parallel iterator that moves out of a vector.\n#[derive(Debug, Clone)]\npub struct IntoIter<T> {\n    vec: Vec<T>,\n}\n\nimpl<T: Send> IntoParallelIterator for Vec<T> {\n    type Item = T;\n    type Iter = IntoIter<T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        IntoIter { vec: self }\n    }\n}\n\nimpl<T: Send> IntoParallelIterator for Box<[T]> {\n    type Item = T;\n    type Iter = IntoIter<T>;\n\n    fn into_par_iter(self) -> Self::Iter {\n        IntoIter { vec: self.into() }\n    }\n}\n\nimpl<T: Send> ParallelIterator for IntoIter<T> {\n    type Item = T;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<T: Send> IndexedParallelIterator for IntoIter<T> {\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.vec.len()\n    }\n\n    fn with_producer<CB>(mut self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        // Drain every item, and then the vector only needs to free its buffer.\n        self.vec.par_drain(..).with_producer(callback)\n    }\n}\n\nimpl<'data, T: Send> ParallelDrainRange<usize> for &'data mut Vec<T> {\n    type Iter = Drain<'data, T>;\n    type Item = T;\n\n    fn par_drain<R: RangeBounds<usize>>(self, range: R) -> Self::Iter {\n        Drain {\n            orig_len: self.len(),\n            range: simplify_range(range, self.len()),\n            vec: self,\n        }\n    }\n}\n\n/// Draining parallel iterator that moves a range out of a vector, but keeps the total capacity.\n#[derive(Debug)]\npub struct Drain<'data, T: Send> {\n    vec: &'data mut Vec<T>,\n    range: Range<usize>,\n    orig_len: usize,\n}\n\nimpl<'data, T: Send> ParallelIterator for Drain<'data, T> {\n    type Item = T;\n\n    fn drive_unindexed<C>(self, consumer: C) -> C::Result\n    where\n        C: UnindexedConsumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn opt_len(&self) -> Option<usize> {\n        Some(self.len())\n    }\n}\n\nimpl<'data, T: Send> IndexedParallelIterator for Drain<'data, T> {\n    fn drive<C>(self, consumer: C) -> C::Result\n    where\n        C: Consumer<Self::Item>,\n    {\n        bridge(self, consumer)\n    }\n\n    fn len(&self) -> usize {\n        self.range.len()\n    }\n\n    fn with_producer<CB>(self, callback: CB) -> CB::Output\n    where\n        CB: ProducerCallback<Self::Item>,\n    {\n        unsafe {\n            // Make the vector forget about the drained items, and temporarily the tail too.\n            self.vec.set_len(self.range.start);\n\n            // Create the producer as the exclusive \"owner\" of the slice.\n            let producer = DrainProducer::from_vec(self.vec, self.range.len());\n\n            // The producer will move or drop each item from the drained range.\n            callback.callback(producer)\n        }\n    }\n}\n\nimpl<'data, T: Send> Drop for Drain<'data, T> {\n    fn drop(&mut self) {\n        let Range { start, end } = self.range;\n        if self.vec.len() == self.orig_len {\n            // We must not have produced, so just call a normal drain to remove the items.\n            self.vec.drain(start..end);\n        } else if start == end {\n            // Empty range, so just restore the length to its original state\n            unsafe {\n                self.vec.set_len(self.orig_len);\n            }\n        } else if end < self.orig_len {\n            // The producer was responsible for consuming the drained items.\n            // Move the tail items to their new place, then set the length to include them.\n            unsafe {\n                let ptr = self.vec.as_mut_ptr().add(start);\n                let tail_ptr = self.vec.as_ptr().add(end);\n                let tail_len = self.orig_len - end;\n                ptr::copy(tail_ptr, ptr, tail_len);\n                self.vec.set_len(start + tail_len);\n            }\n        }\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n\npub(crate) struct DrainProducer<'data, T: Send> {\n    slice: &'data mut [T],\n}\n\nimpl<T: Send> DrainProducer<'_, T> {\n    /// Creates a draining producer, which *moves* items from the slice.\n    ///\n    /// Unsafe because `!Copy` data must not be read after the borrow is released.\n    pub(crate) unsafe fn new(slice: &mut [T]) -> DrainProducer<'_, T> {\n        DrainProducer { slice }\n    }\n\n    /// Creates a draining producer, which *moves* items from the tail of the vector.\n    ///\n    /// Unsafe because we're moving from beyond `vec.len()`, so the caller must ensure\n    /// that data is initialized and not read after the borrow is released.\n    unsafe fn from_vec(vec: &mut Vec<T>, len: usize) -> DrainProducer<'_, T> {\n        let start = vec.len();\n        assert!(vec.capacity() - start >= len);\n\n        // The pointer is derived from `Vec` directly, not through a `Deref`,\n        // so it has provenance over the whole allocation.\n        let ptr = vec.as_mut_ptr().add(start);\n        DrainProducer::new(slice::from_raw_parts_mut(ptr, len))\n    }\n}\n\nimpl<'data, T: 'data + Send> Producer for DrainProducer<'data, T> {\n    type Item = T;\n    type IntoIter = SliceDrain<'data, T>;\n\n    fn into_iter(mut self) -> Self::IntoIter {\n        // replace the slice so we don't drop it twice\n        let slice = mem::take(&mut self.slice);\n        SliceDrain {\n            iter: slice.iter_mut(),\n        }\n    }\n\n    fn split_at(mut self, index: usize) -> (Self, Self) {\n        // replace the slice so we don't drop it twice\n        let slice = mem::take(&mut self.slice);\n        let (left, right) = slice.split_at_mut(index);\n        unsafe { (DrainProducer::new(left), DrainProducer::new(right)) }\n    }\n}\n\nimpl<'data, T: 'data + Send> Drop for DrainProducer<'data, T> {\n    fn drop(&mut self) {\n        // extract the slice so we can use `Drop for [T]`\n        let slice_ptr: *mut [T] = mem::take::<&'data mut [T]>(&mut self.slice);\n        unsafe { ptr::drop_in_place::<[T]>(slice_ptr) };\n    }\n}\n\n// ////////////////////////////////////////////////////////////////////////\n\n// like std::vec::Drain, without updating a source Vec\npub(crate) struct SliceDrain<'data, T> {\n    iter: slice::IterMut<'data, T>,\n}\n\nimpl<'data, T: 'data> Iterator for SliceDrain<'data, T> {\n    type Item = T;\n\n    fn next(&mut self) -> Option<T> {\n        // Coerce the pointer early, so we don't keep the\n        // reference that's about to be invalidated.\n        let ptr: *const T = self.iter.next()?;\n        Some(unsafe { ptr::read(ptr) })\n    }\n\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        self.iter.size_hint()\n    }\n\n    fn count(self) -> usize {\n        self.iter.len()\n    }\n}\n\nimpl<'data, T: 'data> DoubleEndedIterator for SliceDrain<'data, T> {\n    fn next_back(&mut self) -> Option<Self::Item> {\n        // Coerce the pointer early, so we don't keep the\n        // reference that's about to be invalidated.\n        let ptr: *const T = self.iter.next_back()?;\n        Some(unsafe { ptr::read(ptr) })\n    }\n}\n\nimpl<'data, T: 'data> ExactSizeIterator for SliceDrain<'data, T> {\n    fn len(&self) -> usize {\n        self.iter.len()\n    }\n}\n\nimpl<'data, T: 'data> iter::FusedIterator for SliceDrain<'data, T> {}\n\nimpl<'data, T: 'data> Drop for SliceDrain<'data, T> {\n    fn drop(&mut self) {\n        // extract the iterator so we can use `Drop for [T]`\n        let slice_ptr: *mut [T] = mem::replace(&mut self.iter, [].iter_mut()).into_slice();\n        unsafe { ptr::drop_in_place::<[T]>(slice_ptr) };\n    }\n}\n"
  },
  {
    "path": "tests/chars.rs",
    "content": "use rayon::prelude::*;\n\n#[test]\nfn half_open_correctness() {\n    let low = char::from_u32(0xD800 - 0x7).unwrap();\n    let high = char::from_u32(0xE000 + 0x7).unwrap();\n\n    let range = low..high;\n    let mut chars: Vec<char> = range.into_par_iter().collect();\n    chars.sort();\n\n    assert_eq!(\n        chars,\n        vec![\n            '\\u{D7F9}', '\\u{D7FA}', '\\u{D7FB}', '\\u{D7FC}', '\\u{D7FD}', '\\u{D7FE}', '\\u{D7FF}',\n            '\\u{E000}', '\\u{E001}', '\\u{E002}', '\\u{E003}', '\\u{E004}', '\\u{E005}', '\\u{E006}',\n        ]\n    );\n}\n\n#[test]\nfn closed_correctness() {\n    let low = char::from_u32(0xD800 - 0x7).unwrap();\n    let high = char::from_u32(0xE000 + 0x7).unwrap();\n\n    let range = low..=high;\n    let mut chars: Vec<char> = range.into_par_iter().collect();\n    chars.sort();\n\n    assert_eq!(\n        chars,\n        vec![\n            '\\u{D7F9}', '\\u{D7FA}', '\\u{D7FB}', '\\u{D7FC}', '\\u{D7FD}', '\\u{D7FE}', '\\u{D7FF}',\n            '\\u{E000}', '\\u{E001}', '\\u{E002}', '\\u{E003}', '\\u{E004}', '\\u{E005}', '\\u{E006}',\n            '\\u{E007}',\n        ]\n    );\n}\n"
  },
  {
    "path": "tests/clones.rs",
    "content": "use rayon::prelude::*;\nuse std::fmt::Debug;\n\nfn check<I>(iter: I)\nwhere\n    I: ParallelIterator<Item: Debug + PartialEq> + Clone,\n{\n    let a: Vec<_> = iter.clone().collect();\n    let b: Vec<_> = iter.collect();\n    assert_eq!(a, b);\n}\n\nfn check_count<I>(iter: I)\nwhere\n    I: ParallelIterator + Clone,\n{\n    assert_eq!(iter.clone().count(), iter.count());\n}\n\n#[test]\nfn clone_binary_heap() {\n    use std::collections::BinaryHeap;\n    let heap: BinaryHeap<_> = (0..1000).collect();\n    check(heap.par_iter());\n    check(heap.into_par_iter());\n}\n\n#[test]\nfn clone_btree_map() {\n    use std::collections::BTreeMap;\n    let map: BTreeMap<_, _> = (0..1000).enumerate().collect();\n    check(map.par_iter());\n}\n\n#[test]\nfn clone_btree_set() {\n    use std::collections::BTreeSet;\n    let set: BTreeSet<_> = (0..1000).collect();\n    check(set.par_iter());\n}\n\n#[test]\nfn clone_hash_map() {\n    use std::collections::HashMap;\n    let map: HashMap<_, _> = (0..1000).enumerate().collect();\n    check(map.par_iter());\n}\n\n#[test]\nfn clone_hash_set() {\n    use std::collections::HashSet;\n    let set: HashSet<_> = (0..1000).collect();\n    check(set.par_iter());\n}\n\n#[test]\nfn clone_linked_list() {\n    use std::collections::LinkedList;\n    let list: LinkedList<_> = (0..1000).collect();\n    check(list.par_iter());\n    check(list.into_par_iter());\n}\n\n#[test]\nfn clone_vec_deque() {\n    use std::collections::VecDeque;\n    let deque: VecDeque<_> = (0..1000).collect();\n    check(deque.par_iter());\n    check(deque.into_par_iter());\n}\n\n#[test]\nfn clone_option() {\n    let option = Some(0);\n    check(option.par_iter());\n    check(option.into_par_iter());\n}\n\n#[test]\nfn clone_result() {\n    let result = Ok::<_, ()>(0);\n    check(result.par_iter());\n    check(result.into_par_iter());\n}\n\n#[test]\nfn clone_range() {\n    check((0..1000).into_par_iter());\n}\n\n#[test]\nfn clone_range_inclusive() {\n    check((0..=1000).into_par_iter());\n}\n\n#[test]\nfn clone_str() {\n    let s = include_str!(\"clones.rs\");\n    check(s.par_chars());\n    check(s.par_lines());\n    check(s.par_split('\\n'));\n    check(s.par_split_inclusive('\\n'));\n    check(s.par_split_terminator('\\n'));\n    check(s.par_split_whitespace());\n    check(s.par_split_ascii_whitespace());\n}\n\n#[test]\nfn clone_vec() {\n    let v: Vec<_> = (0..1000).collect();\n    check(v.par_iter());\n    check(v.par_chunk_by(i32::eq));\n    check(v.par_chunks(42));\n    check(v.par_chunks_exact(42));\n    check(v.par_rchunks(42));\n    check(v.par_rchunks_exact(42));\n    check(v.par_windows(42));\n    check(v.par_split(|x| x % 3 == 0));\n    check(v.par_split_inclusive(|x| x % 3 == 0));\n    check(v.into_par_iter());\n}\n\n#[test]\nfn clone_array() {\n    let a = [0i32; 100];\n    check(a.into_par_iter());\n}\n\n#[test]\nfn clone_adaptors() {\n    let v: Vec<_> = (0..1000).map(Some).collect();\n    check(v.par_iter().by_exponential_blocks());\n    check(v.par_iter().by_uniform_blocks(100));\n    check(v.par_iter().chain(&v));\n    check(v.par_iter().cloned());\n    check(v.par_iter().copied());\n    check(v.par_iter().enumerate());\n    check(v.par_iter().filter(|_| true));\n    check(v.par_iter().filter_map(|x| *x));\n    check(v.par_iter().flat_map(|x| *x));\n    check(v.par_iter().flat_map_iter(|x| *x));\n    check(v.par_iter().flatten());\n    check(v.par_iter().flatten_iter());\n    check(v.par_iter().with_max_len(1).fold(|| 0, |x, _| x));\n    check(v.par_iter().with_max_len(1).fold_with(0, |x, _| x));\n    check(v.par_iter().with_max_len(1).fold_chunks(1, || 0, |x, _| x));\n    check(\n        v.par_iter()\n            .with_max_len(1)\n            .fold_chunks_with(1, 0, |x, _| x),\n    );\n    check(v.par_iter().with_max_len(1).try_fold(|| 0, |_, &x| x));\n    check(v.par_iter().with_max_len(1).try_fold_with(0, |_, &x| x));\n    check(v.par_iter().inspect(|_| ()));\n    check(v.par_iter().update(|_| ()));\n    check(v.par_iter().interleave(&v));\n    check(v.par_iter().interleave_shortest(&v));\n    check(v.par_iter().intersperse(&None));\n    check(v.par_iter().chunks(3));\n    check(v.par_iter().map(|x| x));\n    check(v.par_iter().map_with(0, |_, x| x));\n    check(v.par_iter().map_init(|| 0, |_, x| x));\n    check(v.par_iter().panic_fuse());\n    check(v.par_iter().positions(|_| true));\n    check(v.par_iter().rev());\n    check(v.par_iter().skip(42));\n    check(v.par_iter().skip_any_while(|_| false));\n    check(v.par_iter().take(42));\n    check(v.par_iter().take_any_while(|_| true));\n    check(v.par_iter().cloned().while_some());\n    check(v.par_iter().with_max_len(1));\n    check(v.par_iter().with_min_len(1));\n    check(v.par_iter().zip(&v));\n    check(v.par_iter().zip_eq(&v));\n    check(v.par_iter().step_by(2));\n}\n\n#[test]\nfn clone_counted_adaptors() {\n    let v: Vec<_> = (0..1000).collect();\n    check_count(v.par_iter().skip_any(42));\n    check_count(v.par_iter().take_any(42));\n}\n\n#[test]\nfn clone_empty() {\n    check(rayon::iter::empty::<i32>());\n}\n\n#[test]\nfn clone_once() {\n    check(rayon::iter::once(10));\n}\n\n#[test]\nfn clone_repeat() {\n    let x: Option<i32> = None;\n    check(rayon::iter::repeat(x).while_some());\n    check(rayon::iter::repeat_n(x, 1000));\n}\n\n#[test]\nfn clone_splitter() {\n    check(rayon::iter::split(0..1000, |x| (x, None)));\n}\n\n#[test]\nfn clone_multizip() {\n    let v: &Vec<_> = &(0..1000).collect();\n    check((v,).into_par_iter());\n    check((v, v).into_par_iter());\n    check((v, v, v).into_par_iter());\n    check((v, v, v, v).into_par_iter());\n    check((v, v, v, v, v).into_par_iter());\n    check((v, v, v, v, v, v).into_par_iter());\n    check((v, v, v, v, v, v, v).into_par_iter());\n    check((v, v, v, v, v, v, v, v).into_par_iter());\n    check((v, v, v, v, v, v, v, v, v).into_par_iter());\n    check((v, v, v, v, v, v, v, v, v, v).into_par_iter());\n    check((v, v, v, v, v, v, v, v, v, v, v).into_par_iter());\n    check((v, v, v, v, v, v, v, v, v, v, v, v).into_par_iter());\n}\n"
  },
  {
    "path": "tests/collect.rs",
    "content": "use rayon::prelude::*;\n\nuse std::panic;\nuse std::sync::atomic::AtomicUsize;\nuse std::sync::atomic::Ordering;\nuse std::sync::Mutex;\n\n#[test]\n#[cfg_attr(not(panic = \"unwind\"), ignore)]\nfn collect_drop_on_unwind() {\n    struct Recorddrop<'a>(i64, &'a Mutex<Vec<i64>>);\n\n    impl<'a> Drop for Recorddrop<'a> {\n        fn drop(&mut self) {\n            self.1.lock().unwrap().push(self.0);\n        }\n    }\n\n    let test_collect_panic = |will_panic: bool| {\n        let test_vec_len = 1024;\n        let panic_point = 740;\n\n        let mut inserts = Mutex::new(Vec::new());\n        let mut drops = Mutex::new(Vec::new());\n\n        let mut a = (0..test_vec_len).collect::<Vec<_>>();\n        let b = (0..test_vec_len).collect::<Vec<_>>();\n\n        let _result = panic::catch_unwind(panic::AssertUnwindSafe(|| {\n            let mut result = Vec::new();\n            a.par_iter_mut()\n                .zip(&b)\n                .map(|(&mut a, &b)| {\n                    if a > panic_point && will_panic {\n                        panic!(\"unwinding for test\");\n                    }\n                    let elt = a + b;\n                    inserts.lock().unwrap().push(elt);\n                    Recorddrop(elt, &drops)\n                })\n                .collect_into_vec(&mut result);\n\n            // If we reach this point, this must pass\n            assert_eq!(a.len(), result.len());\n        }));\n\n        let inserts = inserts.get_mut().unwrap();\n        let drops = drops.get_mut().unwrap();\n        println!(\"{inserts:?}\");\n        println!(\"{drops:?}\");\n\n        assert_eq!(inserts.len(), drops.len(), \"Incorrect number of drops\");\n        // sort to normalize order\n        inserts.sort();\n        drops.sort();\n        assert_eq!(inserts, drops, \"Incorrect elements were dropped\");\n    };\n\n    for &should_panic in &[true, false] {\n        test_collect_panic(should_panic);\n    }\n}\n\n#[test]\n#[cfg_attr(not(panic = \"unwind\"), ignore)]\nfn collect_drop_on_unwind_zst() {\n    static INSERTS: AtomicUsize = AtomicUsize::new(0);\n    static DROPS: AtomicUsize = AtomicUsize::new(0);\n\n    struct RecorddropZst;\n\n    impl Drop for RecorddropZst {\n        fn drop(&mut self) {\n            DROPS.fetch_add(1, Ordering::SeqCst);\n        }\n    }\n\n    let test_collect_panic = |will_panic: bool| {\n        INSERTS.store(0, Ordering::SeqCst);\n        DROPS.store(0, Ordering::SeqCst);\n\n        let test_vec_len = 1024;\n        let panic_point = 740;\n\n        let a = (0..test_vec_len).collect::<Vec<_>>();\n\n        let _result = panic::catch_unwind(panic::AssertUnwindSafe(|| {\n            let mut result = Vec::new();\n            a.par_iter()\n                .map(|&a| {\n                    if a > panic_point && will_panic {\n                        panic!(\"unwinding for test\");\n                    }\n                    INSERTS.fetch_add(1, Ordering::SeqCst);\n                    RecorddropZst\n                })\n                .collect_into_vec(&mut result);\n\n            // If we reach this point, this must pass\n            assert_eq!(a.len(), result.len());\n        }));\n\n        let inserts = INSERTS.load(Ordering::SeqCst);\n        let drops = DROPS.load(Ordering::SeqCst);\n\n        assert_eq!(inserts, drops, \"Incorrect number of drops\");\n        assert!(will_panic || drops == test_vec_len)\n    };\n\n    for &should_panic in &[true, false] {\n        test_collect_panic(should_panic);\n    }\n}\n"
  },
  {
    "path": "tests/cross-pool.rs",
    "content": "use rayon::prelude::*;\nuse rayon::ThreadPoolBuilder;\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn cross_pool_busy() {\n    let pool1 = ThreadPoolBuilder::new().num_threads(1).build().unwrap();\n    let pool2 = ThreadPoolBuilder::new().num_threads(1).build().unwrap();\n\n    let n: i32 = 100;\n    let sum: i32 = pool1.install(move || {\n        // Each item will block on pool2, but pool1 can continue processing other work from the\n        // parallel iterator in the meantime. There's a chance that pool1 will still be awake to\n        // see the latch set without being tickled, and then it will drop that stack job. The latch\n        // internals must not assume that the job will still be alive after it's set!\n        (1..=n)\n            .into_par_iter()\n            .map(|i| pool2.install(move || i))\n            .sum()\n    });\n    assert_eq!(sum, n * (n + 1) / 2);\n}\n"
  },
  {
    "path": "tests/debug.rs",
    "content": "use rayon::prelude::*;\nuse std::fmt::Debug;\n\nfn check<I>(iter: I)\nwhere\n    I: ParallelIterator + Debug,\n{\n    println!(\"{iter:?}\");\n}\n\n#[test]\nfn debug_binary_heap() {\n    use std::collections::BinaryHeap;\n    let mut heap: BinaryHeap<_> = (0..10).collect();\n    check(heap.par_iter());\n    check(heap.par_drain());\n    check(heap.into_par_iter());\n}\n\n#[test]\nfn debug_btree_map() {\n    use std::collections::BTreeMap;\n    let mut map: BTreeMap<_, _> = (0..10).enumerate().collect();\n    check(map.par_iter());\n    check(map.par_iter_mut());\n    check(map.into_par_iter());\n}\n\n#[test]\nfn debug_btree_set() {\n    use std::collections::BTreeSet;\n    let set: BTreeSet<_> = (0..10).collect();\n    check(set.par_iter());\n    check(set.into_par_iter());\n}\n\n#[test]\nfn debug_hash_map() {\n    use std::collections::HashMap;\n    let mut map: HashMap<_, _> = (0..10).enumerate().collect();\n    check(map.par_iter());\n    check(map.par_iter_mut());\n    check(map.par_drain());\n    check(map.into_par_iter());\n}\n\n#[test]\nfn debug_hash_set() {\n    use std::collections::HashSet;\n    let mut set: HashSet<_> = (0..10).collect();\n    check(set.par_iter());\n    check(set.par_drain());\n    check(set.into_par_iter());\n}\n\n#[test]\nfn debug_linked_list() {\n    use std::collections::LinkedList;\n    let mut list: LinkedList<_> = (0..10).collect();\n    check(list.par_iter());\n    check(list.par_iter_mut());\n    check(list.into_par_iter());\n}\n\n#[test]\nfn debug_vec_deque() {\n    use std::collections::VecDeque;\n    let mut deque: VecDeque<_> = (0..10).collect();\n    check(deque.par_iter());\n    check(deque.par_iter_mut());\n    check(deque.par_drain(..));\n    check(deque.into_par_iter());\n}\n\n#[test]\nfn debug_option() {\n    let mut option = Some(0);\n    check(option.par_iter());\n    check(option.par_iter_mut());\n    check(option.into_par_iter());\n}\n\n#[test]\nfn debug_result() {\n    let mut result = Ok::<_, ()>(0);\n    check(result.par_iter());\n    check(result.par_iter_mut());\n    check(result.into_par_iter());\n}\n\n#[test]\nfn debug_range() {\n    check((0..10).into_par_iter());\n}\n\n#[test]\nfn debug_range_inclusive() {\n    check((0..=10).into_par_iter());\n}\n\n#[test]\nfn debug_str() {\n    let s = \"a b c d\\ne f g\";\n    check(s.par_chars());\n    check(s.par_lines());\n    check(s.par_split('\\n'));\n    check(s.par_split_inclusive('\\n'));\n    check(s.par_split_terminator('\\n'));\n    check(s.par_split_whitespace());\n    check(s.par_split_ascii_whitespace());\n}\n\n#[test]\nfn debug_string() {\n    let mut s = \"a b c d\\ne f g\".to_string();\n    s.par_drain(..);\n}\n\n#[test]\nfn debug_vec() {\n    let mut v: Vec<_> = (0..10).collect();\n    check(v.par_iter());\n    check(v.par_iter_mut());\n    check(v.par_chunk_by(i32::eq));\n    check(v.par_chunk_by_mut(i32::eq));\n    check(v.par_chunks(42));\n    check(v.par_chunks_exact(42));\n    check(v.par_chunks_mut(42));\n    check(v.par_chunks_exact_mut(42));\n    check(v.par_rchunks(42));\n    check(v.par_rchunks_exact(42));\n    check(v.par_rchunks_mut(42));\n    check(v.par_rchunks_exact_mut(42));\n    check(v.par_windows(42));\n    check(v.par_split(|x| x % 3 == 0));\n    check(v.par_split_inclusive(|x| x % 3 == 0));\n    check(v.par_split_mut(|x| x % 3 == 0));\n    check(v.par_split_inclusive_mut(|x| x % 3 == 0));\n    check(v.par_drain(..));\n    check(v.into_par_iter());\n}\n\n#[test]\nfn debug_array() {\n    let a = [0i32; 10];\n    check(a.into_par_iter());\n}\n\n#[test]\nfn debug_adaptors() {\n    let v: Vec<_> = (0..10).collect();\n    check(v.par_iter().by_exponential_blocks());\n    check(v.par_iter().by_uniform_blocks(5));\n    check(v.par_iter().chain(&v));\n    check(v.par_iter().cloned());\n    check(v.par_iter().copied());\n    check(v.par_iter().enumerate());\n    check(v.par_iter().filter(|_| true));\n    check(v.par_iter().filter_map(Some));\n    check(v.par_iter().flat_map(Some));\n    check(v.par_iter().flat_map_iter(Some));\n    check(v.par_iter().map(Some).flatten());\n    check(v.par_iter().map(Some).flatten_iter());\n    check(v.par_iter().fold(|| 0, |x, _| x));\n    check(v.par_iter().fold_with(0, |x, _| x));\n    check(v.par_iter().fold_chunks(3, || 0, |x, _| x));\n    check(v.par_iter().fold_chunks_with(3, 0, |x, _| x));\n    check(v.par_iter().try_fold(|| 0, |x, _| Some(x)));\n    check(v.par_iter().try_fold_with(0, |x, _| Some(x)));\n    check(v.par_iter().inspect(|_| ()));\n    check(v.par_iter().update(|_| ()));\n    check(v.par_iter().interleave(&v));\n    check(v.par_iter().interleave_shortest(&v));\n    check(v.par_iter().intersperse(&-1));\n    check(v.par_iter().chunks(3));\n    check(v.par_iter().map(|x| x));\n    check(v.par_iter().map_with(0, |_, x| x));\n    check(v.par_iter().map_init(|| 0, |_, x| x));\n    check(v.par_iter().panic_fuse());\n    check(v.par_iter().positions(|_| true));\n    check(v.par_iter().rev());\n    check(v.par_iter().skip(1));\n    check(v.par_iter().skip_any(1));\n    check(v.par_iter().skip_any_while(|_| false));\n    check(v.par_iter().take(1));\n    check(v.par_iter().take_any(1));\n    check(v.par_iter().take_any_while(|_| true));\n    check(v.par_iter().map(Some).while_some());\n    check(v.par_iter().with_max_len(1));\n    check(v.par_iter().with_min_len(1));\n    check(v.par_iter().zip(&v));\n    check(v.par_iter().zip_eq(&v));\n    check(v.par_iter().step_by(2));\n}\n\n#[test]\nfn debug_empty() {\n    check(rayon::iter::empty::<i32>());\n}\n\n#[test]\nfn debug_once() {\n    check(rayon::iter::once(10));\n}\n\n#[test]\nfn debug_repeat() {\n    let x: Option<i32> = None;\n    check(rayon::iter::repeat(x));\n    check(rayon::iter::repeat_n(x, 10));\n}\n\n#[test]\nfn debug_splitter() {\n    check(rayon::iter::split(0..10, |x| (x, None)));\n}\n\n#[test]\nfn debug_multizip() {\n    let v: &Vec<_> = &(0..10).collect();\n    check((v,).into_par_iter());\n    check((v, v).into_par_iter());\n    check((v, v, v).into_par_iter());\n    check((v, v, v, v).into_par_iter());\n    check((v, v, v, v, v).into_par_iter());\n    check((v, v, v, v, v, v).into_par_iter());\n    check((v, v, v, v, v, v, v).into_par_iter());\n    check((v, v, v, v, v, v, v, v).into_par_iter());\n    check((v, v, v, v, v, v, v, v, v).into_par_iter());\n    check((v, v, v, v, v, v, v, v, v, v).into_par_iter());\n    check((v, v, v, v, v, v, v, v, v, v, v).into_par_iter());\n    check((v, v, v, v, v, v, v, v, v, v, v, v).into_par_iter());\n}\n"
  },
  {
    "path": "tests/drain_vec.rs",
    "content": "use rayon::prelude::*;\n\n#[test]\nfn drain_vec_yielded() {\n    let mut vec_org = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];\n\n    let yielded = vec_org.par_drain(0..5).collect::<Vec<_>>();\n\n    assert_eq!(&yielded, &[0, 1, 2, 3, 4]);\n    assert_eq!(&vec_org, &[5, 6, 7, 8, 9]);\n}\n\n#[test]\nfn drain_vec_dropped() {\n    let mut vec_org = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];\n\n    let yielded = vec_org.par_drain(0..5);\n\n    drop(yielded);\n    assert_eq!(&vec_org, &[5, 6, 7, 8, 9]);\n}\n\n#[test]\nfn drain_vec_empty_range_yielded() {\n    let mut vec_org = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];\n\n    let yielded = vec_org.par_drain(5..5).collect::<Vec<_>>();\n\n    assert_eq!(&yielded, &[]);\n    assert_eq!(&vec_org, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);\n}\n\n#[test]\nfn drain_vec_empty_range_dropped() {\n    let mut vec_org = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];\n\n    let yielded = vec_org.par_drain(5..5);\n\n    drop(yielded);\n    assert_eq!(&vec_org, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);\n}\n"
  },
  {
    "path": "tests/intersperse.rs",
    "content": "use rayon::prelude::*;\n\n#[test]\nfn check_intersperse() {\n    let v: Vec<_> = (0..1000).into_par_iter().intersperse(-1).collect();\n    assert_eq!(v.len(), 1999);\n    for (i, x) in v.into_iter().enumerate() {\n        assert_eq!(x, if i % 2 == 0 { i as i32 / 2 } else { -1 });\n    }\n}\n\n#[test]\nfn check_intersperse_again() {\n    let v: Vec<_> = (0..1000)\n        .into_par_iter()\n        .intersperse(-1)\n        .intersperse(-2)\n        .collect();\n    assert_eq!(v.len(), 3997);\n    for (i, x) in v.into_iter().enumerate() {\n        let y = match i % 4 {\n            0 => i as i32 / 4,\n            2 => -1,\n            _ => -2,\n        };\n        assert_eq!(x, y);\n    }\n}\n\n#[test]\nfn check_intersperse_unindexed() {\n    let v: Vec<_> = (0..1000).map(|i| i.to_string()).collect();\n    let s = v.join(\",\");\n    let s2 = v.join(\";\");\n    let par: String = s.par_split(',').intersperse(\";\").collect();\n    assert_eq!(par, s2);\n}\n\n#[test]\nfn check_intersperse_producer() {\n    (0..1000)\n        .into_par_iter()\n        .intersperse(-1)\n        .zip_eq(0..1999)\n        .for_each(|(x, i)| {\n            assert_eq!(x, if i % 2 == 0 { i / 2 } else { -1 });\n        });\n}\n\n#[test]\nfn check_intersperse_rev() {\n    (0..1000)\n        .into_par_iter()\n        .intersperse(-1)\n        .zip_eq(0..1999)\n        .rev()\n        .for_each(|(x, i)| {\n            assert_eq!(x, if i % 2 == 0 { i / 2 } else { -1 });\n        });\n}\n"
  },
  {
    "path": "tests/issue671-unzip.rs",
    "content": "#![type_length_limit = \"10000\"]\n\nuse rayon::prelude::*;\n\n#[test]\nfn type_length_limit() {\n    let input = vec![1, 2, 3, 4, 5];\n    let (indexes, (squares, cubes)): (Vec<_>, (Vec<_>, Vec<_>)) = input\n        .par_iter()\n        .map(|x| (x * x, x * x * x))\n        .enumerate()\n        .unzip();\n\n    drop(indexes);\n    drop(squares);\n    drop(cubes);\n}\n"
  },
  {
    "path": "tests/issue671.rs",
    "content": "#![type_length_limit = \"500000\"]\n\nuse rayon::prelude::*;\n\n#[test]\nfn type_length_limit() {\n    let _ = Vec::<Result<(), ()>>::new()\n        .into_par_iter()\n        .map(|x| x)\n        .map(|x| x)\n        .map(|x| x)\n        .map(|x| x)\n        .map(|x| x)\n        .map(|x| x)\n        .collect::<Result<(), ()>>();\n}\n"
  },
  {
    "path": "tests/iter_panic.rs",
    "content": "use rayon::prelude::*;\nuse rayon::ThreadPoolBuilder;\nuse std::ops::Range;\nuse std::panic::{self, UnwindSafe};\nuse std::sync::atomic::{AtomicUsize, Ordering};\n\nconst ITER: Range<i32> = 0..0x1_0000;\nconst PANIC: i32 = 0xC000;\n\nfn check(&i: &i32) {\n    if i == PANIC {\n        panic!(\"boom\")\n    }\n}\n\n#[test]\n#[should_panic(expected = \"boom\")]\nfn iter_panic() {\n    ITER.into_par_iter().for_each(|i| check(&i));\n}\n\n#[test]\n#[cfg_attr(not(panic = \"unwind\"), ignore)]\nfn iter_panic_fuse() {\n    // We only use a single thread in order to make the behavior\n    // of 'panic_fuse' deterministic\n    let pool = ThreadPoolBuilder::new().num_threads(1).build().unwrap();\n\n    pool.install(|| {\n        fn count(iter: impl ParallelIterator + UnwindSafe) -> usize {\n            let count = AtomicUsize::new(0);\n            let result = panic::catch_unwind(|| {\n                iter.for_each(|_| {\n                    count.fetch_add(1, Ordering::Relaxed);\n                });\n            });\n            assert!(result.is_err());\n            count.into_inner()\n        }\n\n        // Without `panic_fuse()`, we'll reach every item except the panicking one.\n        let expected = ITER.len() - 1;\n        let iter = ITER.into_par_iter().with_max_len(1);\n        assert_eq!(count(iter.clone().inspect(check)), expected);\n\n        // With `panic_fuse()` anywhere in the chain, we'll reach fewer items.\n        assert!(count(iter.clone().inspect(check).panic_fuse()) < expected);\n        assert!(count(iter.clone().panic_fuse().inspect(check)) < expected);\n\n        // Try in reverse to be sure we hit the producer case.\n        assert!(count(iter.panic_fuse().inspect(check).rev()) < expected);\n    });\n}\n"
  },
  {
    "path": "tests/named-threads.rs",
    "content": "use std::collections::HashSet;\n\nuse rayon::prelude::*;\nuse rayon::*;\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn named_threads() {\n    ThreadPoolBuilder::new()\n        .thread_name(|i| format!(\"hello-name-test-{i}\"))\n        .build_global()\n        .unwrap();\n\n    const N: usize = 10000;\n\n    let thread_names = (0..N)\n        .into_par_iter()\n        .flat_map(|_| ::std::thread::current().name().map(str::to_owned))\n        .collect::<HashSet<String>>();\n\n    let all_contains_name = thread_names\n        .iter()\n        .all(|name| name.starts_with(\"hello-name-test-\"));\n    assert!(all_contains_name);\n}\n"
  },
  {
    "path": "tests/octillion.rs",
    "content": "use rayon::prelude::*;\n\nconst OCTILLION: u128 = 1_000_000_000_000_000_000_000_000_000;\n\n/// Produce a parallel iterator for 0u128..10²⁷\nfn octillion() -> rayon::range::Iter<u128> {\n    (0..OCTILLION).into_par_iter()\n}\n\n/// Produce a parallel iterator for 0u128..=10²⁷\nfn octillion_inclusive() -> rayon::range_inclusive::Iter<u128> {\n    (0..=OCTILLION).into_par_iter()\n}\n\n/// Produce a parallel iterator for 0u128..10²⁷ using `flat_map`\nfn octillion_flat() -> impl ParallelIterator<Item = u128> {\n    (0u32..1_000_000_000)\n        .into_par_iter()\n        .with_max_len(1_000)\n        .map(|i| u64::from(i) * 1_000_000_000)\n        .flat_map(|i| {\n            (0u32..1_000_000_000)\n                .into_par_iter()\n                .with_max_len(1_000)\n                .map(move |j| i + u64::from(j))\n        })\n        .map(|i| u128::from(i) * 1_000_000_000)\n        .flat_map(|i| {\n            (0u32..1_000_000_000)\n                .into_par_iter()\n                .with_max_len(1_000)\n                .map(move |j| i + u128::from(j))\n        })\n}\n\n// NOTE: `find_first` and `find_last` currently take too long on 32-bit targets,\n// because the `AtomicUsize` match position has much too limited resolution.\n\n#[test]\n#[cfg_attr(not(target_pointer_width = \"64\"), ignore)]\nfn find_first_octillion() {\n    let x = octillion().find_first(|_| true);\n    assert_eq!(x, Some(0));\n}\n\n#[test]\n#[cfg_attr(not(target_pointer_width = \"64\"), ignore)]\nfn find_first_octillion_inclusive() {\n    let x = octillion_inclusive().find_first(|_| true);\n    assert_eq!(x, Some(0));\n}\n\n#[test]\n#[cfg_attr(not(target_pointer_width = \"64\"), ignore)]\nfn find_first_octillion_flat() {\n    let x = octillion_flat().find_first(|_| true);\n    assert_eq!(x, Some(0));\n}\n\nfn two_threads<F: Send + FnOnce() -> R, R: Send>(f: F) -> R {\n    // FIXME: If we don't use at least two threads, then we end up walking\n    // through the entire iterator sequentially, without the benefit of any\n    // short-circuiting.  We probably don't want testing to wait that long. ;)\n    let builder = rayon::ThreadPoolBuilder::new().num_threads(2);\n    let pool = builder.build().unwrap();\n\n    pool.install(f)\n}\n\n#[test]\n#[cfg_attr(\n    any(\n        not(target_pointer_width = \"64\"),\n        target_os = \"emscripten\",\n        target_family = \"wasm\"\n    ),\n    ignore\n)]\nfn find_last_octillion() {\n    // It would be nice if `find_last` could prioritize the later splits,\n    // basically flipping the `join` args, without needing indexed `rev`.\n    // (or could we have an unindexed `rev`?)\n    let x = two_threads(|| octillion().find_last(|_| true));\n    assert_eq!(x, Some(OCTILLION - 1));\n}\n\n#[test]\n#[cfg_attr(\n    any(\n        not(target_pointer_width = \"64\"),\n        target_os = \"emscripten\",\n        target_family = \"wasm\"\n    ),\n    ignore\n)]\nfn find_last_octillion_inclusive() {\n    let x = two_threads(|| octillion_inclusive().find_last(|_| true));\n    assert_eq!(x, Some(OCTILLION));\n}\n\n#[test]\n#[cfg_attr(\n    any(\n        not(target_pointer_width = \"64\"),\n        target_os = \"emscripten\",\n        target_family = \"wasm\"\n    ),\n    ignore\n)]\nfn find_last_octillion_flat() {\n    let x = two_threads(|| octillion_flat().find_last(|_| true));\n    assert_eq!(x, Some(OCTILLION - 1));\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn find_any_octillion() {\n    let x = two_threads(|| octillion().find_any(|x| *x > OCTILLION / 2));\n    assert!(x.is_some());\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn find_any_octillion_flat() {\n    let x = two_threads(|| octillion_flat().find_any(|x| *x > OCTILLION / 2));\n    assert!(x.is_some());\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn filter_find_any_octillion() {\n    let x = two_threads(|| {\n        octillion()\n            .filter(|x| *x > OCTILLION / 2)\n            .find_any(|_| true)\n    });\n    assert!(x.is_some());\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn filter_find_any_octillion_flat() {\n    let x = two_threads(|| {\n        octillion_flat()\n            .filter(|x| *x > OCTILLION / 2)\n            .find_any(|_| true)\n    });\n    assert!(x.is_some());\n}\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn fold_find_any_octillion_flat() {\n    let x = two_threads(|| octillion_flat().fold(|| (), |_, _| ()).find_any(|_| true));\n    assert!(x.is_some());\n}\n"
  },
  {
    "path": "tests/par_bridge_recursion.rs",
    "content": "use rayon::prelude::*;\nuse std::iter::once_with;\n\nconst N: usize = 100_000;\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn par_bridge_recursion() {\n    let pool = rayon::ThreadPoolBuilder::new()\n        .num_threads(10)\n        .build()\n        .unwrap();\n\n    let seq: Vec<_> = (0..N).map(|i| (i, i.to_string())).collect();\n\n    pool.broadcast(|_| {\n        let mut par: Vec<_> = (0..N)\n            .into_par_iter()\n            .flat_map(|i| {\n                once_with(move || {\n                    // Using rayon within the serial iterator creates an opportunity for\n                    // work-stealing to make par_bridge's mutex accidentally recursive.\n                    rayon::join(move || i, move || i.to_string())\n                })\n                .par_bridge()\n            })\n            .collect();\n        par.par_sort_unstable();\n        assert_eq!(seq, par);\n    });\n}\n"
  },
  {
    "path": "tests/producer_split_at.rs",
    "content": "use rayon::iter::plumbing::*;\nuse rayon::prelude::*;\nuse std::fmt::Debug;\n\n/// Stress-test indexes for `Producer::split_at`.\nfn check<F, I>(expected: &[I::Item], mut f: F)\nwhere\n    F: FnMut() -> I,\n    I: IntoParallelIterator<Iter: IndexedParallelIterator, Item: PartialEq + Debug>,\n{\n    map_triples(expected.len() + 1, |i, j, k| {\n        Split::forward(f(), i, j, k, expected);\n        Split::reverse(f(), i, j, k, expected);\n    });\n}\n\nfn map_triples<F>(end: usize, mut f: F)\nwhere\n    F: FnMut(usize, usize, usize),\n{\n    for i in 0..end {\n        for j in i..end {\n            for k in j..end {\n                f(i, j, k);\n            }\n        }\n    }\n}\n\n#[derive(Debug)]\nstruct Split {\n    i: usize,\n    j: usize,\n    k: usize,\n    reverse: bool,\n}\n\nimpl Split {\n    fn forward<I>(iter: I, i: usize, j: usize, k: usize, expected: &[I::Item])\n    where\n        I: IntoParallelIterator<Iter: IndexedParallelIterator, Item: PartialEq + Debug>,\n    {\n        let result = iter.into_par_iter().with_producer(Split {\n            i,\n            j,\n            k,\n            reverse: false,\n        });\n        assert_eq!(result, expected);\n    }\n\n    fn reverse<I>(iter: I, i: usize, j: usize, k: usize, expected: &[I::Item])\n    where\n        I: IntoParallelIterator<Iter: IndexedParallelIterator, Item: PartialEq + Debug>,\n    {\n        let result = iter.into_par_iter().with_producer(Split {\n            i,\n            j,\n            k,\n            reverse: true,\n        });\n        assert!(result.iter().eq(expected.iter().rev()));\n    }\n}\n\nimpl<T> ProducerCallback<T> for Split {\n    type Output = Vec<T>;\n\n    fn callback<P>(self, producer: P) -> Self::Output\n    where\n        P: Producer<Item = T>,\n    {\n        println!(\"{self:?}\");\n\n        // Splitting the outer indexes first gets us an arbitrary mid section,\n        // which we then split further to get full test coverage.\n        let (left, d) = producer.split_at(self.k);\n        let (a, mid) = left.split_at(self.i);\n        let (b, c) = mid.split_at(self.j - self.i);\n\n        let a = a.into_iter();\n        let b = b.into_iter();\n        let c = c.into_iter();\n        let d = d.into_iter();\n\n        check_len(&a, self.i);\n        check_len(&b, self.j - self.i);\n        check_len(&c, self.k - self.j);\n\n        let chain = a.chain(b).chain(c).chain(d);\n        if self.reverse {\n            chain.rev().collect()\n        } else {\n            chain.collect()\n        }\n    }\n}\n\nfn check_len<I: ExactSizeIterator>(iter: &I, len: usize) {\n    assert_eq!(iter.size_hint(), (len, Some(len)));\n    assert_eq!(iter.len(), len);\n}\n\n// **** Base Producers ****\n\n#[test]\nfn array() {\n    let a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];\n    check(&a, || a);\n}\n\n#[test]\nfn empty() {\n    check(&[], rayon::iter::empty::<i32>);\n}\n\n#[test]\nfn once() {\n    check(&[42], || rayon::iter::once(42));\n}\n\n#[test]\nfn option() {\n    check(&[42], || Some(42));\n}\n\n#[test]\nfn range() {\n    let v: Vec<_> = (0..10).collect();\n    check(&v, || 0..10);\n}\n\n#[test]\nfn range_inclusive() {\n    let v: Vec<_> = (0u16..=10).collect();\n    check(&v, || 0u16..=10);\n}\n\n#[test]\nfn repeat_n() {\n    let v: Vec<_> = std::iter::repeat(1).take(5).collect();\n    check(&v, || rayon::iter::repeat_n(1, 5));\n}\n\n#[test]\nfn slice_iter() {\n    let s: Vec<_> = (0..10).collect();\n    let v: Vec<_> = s.iter().collect();\n    check(&v, || &s);\n}\n\n#[test]\nfn slice_iter_mut() {\n    let mut s: Vec<_> = (0..10).collect();\n    let mut v: Vec<_> = s.clone();\n    let expected: Vec<_> = v.iter_mut().collect();\n\n    map_triples(expected.len() + 1, |i, j, k| {\n        Split::forward(s.par_iter_mut(), i, j, k, &expected);\n        Split::reverse(s.par_iter_mut(), i, j, k, &expected);\n    });\n}\n\n#[test]\nfn slice_chunks() {\n    let s: Vec<_> = (0..10).collect();\n    for len in 1..s.len() + 2 {\n        let v: Vec<_> = s.chunks(len).collect();\n        check(&v, || s.par_chunks(len));\n    }\n}\n\n#[test]\nfn slice_chunks_exact() {\n    let s: Vec<_> = (0..10).collect();\n    for len in 1..s.len() + 2 {\n        let v: Vec<_> = s.chunks_exact(len).collect();\n        check(&v, || s.par_chunks_exact(len));\n    }\n}\n\n#[test]\nfn slice_chunks_mut() {\n    let mut s: Vec<_> = (0..10).collect();\n    let mut v: Vec<_> = s.clone();\n    for len in 1..s.len() + 2 {\n        let expected: Vec<_> = v.chunks_mut(len).collect();\n        map_triples(expected.len() + 1, |i, j, k| {\n            Split::forward(s.par_chunks_mut(len), i, j, k, &expected);\n            Split::reverse(s.par_chunks_mut(len), i, j, k, &expected);\n        });\n    }\n}\n\n#[test]\nfn slice_chunks_exact_mut() {\n    let mut s: Vec<_> = (0..10).collect();\n    let mut v: Vec<_> = s.clone();\n    for len in 1..s.len() + 2 {\n        let expected: Vec<_> = v.chunks_exact_mut(len).collect();\n        map_triples(expected.len() + 1, |i, j, k| {\n            Split::forward(s.par_chunks_exact_mut(len), i, j, k, &expected);\n            Split::reverse(s.par_chunks_exact_mut(len), i, j, k, &expected);\n        });\n    }\n}\n\n#[test]\nfn slice_rchunks() {\n    let s: Vec<_> = (0..10).collect();\n    for len in 1..s.len() + 2 {\n        let v: Vec<_> = s.rchunks(len).collect();\n        check(&v, || s.par_rchunks(len));\n    }\n}\n\n#[test]\nfn slice_rchunks_exact() {\n    let s: Vec<_> = (0..10).collect();\n    for len in 1..s.len() + 2 {\n        let v: Vec<_> = s.rchunks_exact(len).collect();\n        check(&v, || s.par_rchunks_exact(len));\n    }\n}\n\n#[test]\nfn slice_rchunks_mut() {\n    let mut s: Vec<_> = (0..10).collect();\n    let mut v: Vec<_> = s.clone();\n    for len in 1..s.len() + 2 {\n        let expected: Vec<_> = v.rchunks_mut(len).collect();\n        map_triples(expected.len() + 1, |i, j, k| {\n            Split::forward(s.par_rchunks_mut(len), i, j, k, &expected);\n            Split::reverse(s.par_rchunks_mut(len), i, j, k, &expected);\n        });\n    }\n}\n\n#[test]\nfn slice_rchunks_exact_mut() {\n    let mut s: Vec<_> = (0..10).collect();\n    let mut v: Vec<_> = s.clone();\n    for len in 1..s.len() + 2 {\n        let expected: Vec<_> = v.rchunks_exact_mut(len).collect();\n        map_triples(expected.len() + 1, |i, j, k| {\n            Split::forward(s.par_rchunks_exact_mut(len), i, j, k, &expected);\n            Split::reverse(s.par_rchunks_exact_mut(len), i, j, k, &expected);\n        });\n    }\n}\n\n#[test]\nfn slice_windows() {\n    let s: Vec<_> = (0..10).collect();\n    let v: Vec<_> = s.windows(2).collect();\n    check(&v, || s.par_windows(2));\n}\n\n#[test]\nfn vec() {\n    let v: Vec<_> = (0..10).collect();\n    check(&v, || v.clone());\n}\n\n// **** Adaptors ****\n\n#[test]\nfn chain() {\n    let v: Vec<_> = (0..10).collect();\n    check(&v, || (0..5).into_par_iter().chain(5..10));\n}\n\n#[test]\nfn cloned() {\n    let v: Vec<_> = (0..10).collect();\n    check(&v, || v.par_iter().cloned());\n}\n\n#[test]\nfn copied() {\n    let v: Vec<_> = (0..10).collect();\n    check(&v, || v.par_iter().copied());\n}\n\n#[test]\nfn enumerate() {\n    let v: Vec<_> = (0..10).enumerate().collect();\n    check(&v, || (0..10).into_par_iter().enumerate());\n}\n\n#[test]\nfn step_by() {\n    let v: Vec<_> = (0..10).step_by(2).collect();\n    check(&v, || (0..10).into_par_iter().step_by(2))\n}\n\n#[test]\nfn step_by_unaligned() {\n    let v: Vec<_> = (0..10).step_by(3).collect();\n    check(&v, || (0..10).into_par_iter().step_by(3))\n}\n\n#[test]\nfn inspect() {\n    let v: Vec<_> = (0..10).collect();\n    check(&v, || (0..10).into_par_iter().inspect(|_| ()));\n}\n\n#[test]\nfn update() {\n    let v: Vec<_> = (0..10).collect();\n    check(&v, || (0..10).into_par_iter().update(|_| ()));\n}\n\n#[test]\nfn interleave() {\n    let v = [0, 10, 1, 11, 2, 12, 3, 4];\n    check(&v, || (0..5).into_par_iter().interleave(10..13));\n    check(&v[..6], || (0..3).into_par_iter().interleave(10..13));\n\n    let v = [0, 10, 1, 11, 2, 12, 13, 14];\n    check(&v, || (0..3).into_par_iter().interleave(10..15));\n}\n\n#[test]\nfn intersperse() {\n    let v = [0, -1, 1, -1, 2, -1, 3, -1, 4];\n    check(&v, || (0..5).into_par_iter().intersperse(-1));\n}\n\n#[test]\nfn chunks() {\n    let s: Vec<_> = (0..10).collect();\n    let v: Vec<_> = s.chunks(2).map(|c| c.to_vec()).collect();\n    check(&v, || s.par_iter().cloned().chunks(2));\n}\n\n#[test]\nfn map() {\n    let v: Vec<_> = (0..10).collect();\n    check(&v, || v.par_iter().map(Clone::clone));\n}\n\n#[test]\nfn map_with() {\n    let v: Vec<_> = (0..10).collect();\n    check(&v, || v.par_iter().map_with(vec![0], |_, &x| x));\n}\n\n#[test]\nfn map_init() {\n    let v: Vec<_> = (0..10).collect();\n    check(&v, || v.par_iter().map_init(|| vec![0], |_, &x| x));\n}\n\n#[test]\nfn panic_fuse() {\n    let v: Vec<_> = (0..10).collect();\n    check(&v, || (0..10).into_par_iter().panic_fuse());\n}\n\n#[test]\nfn rev() {\n    let v: Vec<_> = (0..10).rev().collect();\n    check(&v, || (0..10).into_par_iter().rev());\n}\n\n#[test]\nfn with_max_len() {\n    let v: Vec<_> = (0..10).collect();\n    check(&v, || (0..10).into_par_iter().with_max_len(1));\n}\n\n#[test]\nfn with_min_len() {\n    let v: Vec<_> = (0..10).collect();\n    check(&v, || (0..10).into_par_iter().with_min_len(1));\n}\n\n#[test]\nfn zip() {\n    let v: Vec<_> = (0..10).zip(10..20).collect();\n    check(&v, || (0..10).into_par_iter().zip(10..20));\n    check(&v[..5], || (0..5).into_par_iter().zip(10..20));\n    check(&v[..5], || (0..10).into_par_iter().zip(10..15));\n}\n"
  },
  {
    "path": "tests/sort-panic-safe.rs",
    "content": "use rand::distr::Uniform;\nuse rand::{rng, Rng};\nuse rayon::prelude::*;\nuse std::cell::Cell;\nuse std::cmp::Ordering;\nuse std::panic;\nuse std::sync::atomic::AtomicUsize;\nuse std::sync::atomic::Ordering::Relaxed;\nuse std::thread;\n\nconst LEN: usize = 20_000;\n\nstatic VERSIONS: AtomicUsize = AtomicUsize::new(0);\n\nstatic DROP_COUNTS: [AtomicUsize; LEN] = [const { AtomicUsize::new(0) }; LEN];\n\n#[derive(Clone, Eq)]\nstruct DropCounter {\n    x: u32,\n    id: usize,\n    version: Cell<usize>,\n}\n\nimpl PartialEq for DropCounter {\n    fn eq(&self, other: &Self) -> bool {\n        self.partial_cmp(other) == Some(Ordering::Equal)\n    }\n}\n\n#[allow(clippy::non_canonical_partial_ord_impl)]\nimpl PartialOrd for DropCounter {\n    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {\n        self.version.set(self.version.get() + 1);\n        other.version.set(other.version.get() + 1);\n        VERSIONS.fetch_add(2, Relaxed);\n        self.x.partial_cmp(&other.x)\n    }\n}\n\nimpl Ord for DropCounter {\n    fn cmp(&self, other: &Self) -> Ordering {\n        self.partial_cmp(other).unwrap()\n    }\n}\n\nimpl Drop for DropCounter {\n    fn drop(&mut self) {\n        DROP_COUNTS[self.id].fetch_add(1, Relaxed);\n        VERSIONS.fetch_sub(self.version.get(), Relaxed);\n    }\n}\n\nmacro_rules! test {\n    ($input:ident, $func:ident) => {\n        let len = $input.len();\n\n        // Work out the total number of comparisons required to sort\n        // this array...\n        let count = AtomicUsize::new(0);\n        $input.to_owned().$func(|a, b| {\n            count.fetch_add(1, Relaxed);\n            a.cmp(b)\n        });\n\n        let mut panic_countdown = count.load(Relaxed);\n        let step = if len <= 100 {\n            1\n        } else {\n            Ord::max(1, panic_countdown / 10)\n        };\n\n        // ... and then panic after each `step` comparisons.\n        loop {\n            // Refresh the counters.\n            VERSIONS.store(0, Relaxed);\n            for i in 0..len {\n                DROP_COUNTS[i].store(0, Relaxed);\n            }\n\n            let v = $input.to_owned();\n            let _ = thread::spawn(move || {\n                let mut v = v;\n                let panic_countdown = AtomicUsize::new(panic_countdown);\n                v.$func(|a, b| {\n                    if panic_countdown.fetch_sub(1, Relaxed) == 1 {\n                        SILENCE_PANIC.set(true);\n                        panic!();\n                    }\n                    a.cmp(b)\n                })\n            })\n            .join();\n\n            // Check that the number of things dropped is exactly\n            // what we expect (i.e. the contents of `v`).\n            for (i, c) in DROP_COUNTS.iter().enumerate().take(len) {\n                let count = c.load(Relaxed);\n                assert!(\n                    count == 1,\n                    \"found drop count == {} for i == {}, len == {}\",\n                    count,\n                    i,\n                    len\n                );\n            }\n\n            // Check that the most recent versions of values were dropped.\n            assert_eq!(VERSIONS.load(Relaxed), 0);\n\n            if panic_countdown < step {\n                break;\n            }\n            panic_countdown -= step;\n        }\n    };\n}\n\nthread_local!(static SILENCE_PANIC: Cell<bool> = const { Cell::new(false) });\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nfn sort_panic_safe() {\n    let prev = panic::take_hook();\n    panic::set_hook(Box::new(move |info| {\n        if !SILENCE_PANIC.get() {\n            prev(info);\n        }\n    }));\n\n    for &len in &[1, 2, 3, 4, 5, 10, 20, 100, 500, 5_000, 20_000] {\n        let len_dist = Uniform::new(0, len).unwrap();\n        for &modulus in &[5, 30, 1_000, 20_000] {\n            for &has_runs in &[false, true] {\n                let mut rng = rng();\n                let mut input = (0..len)\n                    .map(|id| DropCounter {\n                        x: rng.random_range(0..modulus),\n                        id,\n                        version: Cell::new(0),\n                    })\n                    .collect::<Vec<_>>();\n\n                if has_runs {\n                    for c in &mut input {\n                        c.x = c.id as u32;\n                    }\n\n                    for _ in 0..5 {\n                        let a = rng.sample(len_dist);\n                        let b = rng.sample(len_dist);\n                        if a < b {\n                            input[a..b].reverse();\n                        } else {\n                            input.swap(a, b);\n                        }\n                    }\n                }\n\n                test!(input, par_sort_by);\n                test!(input, par_sort_unstable_by);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "tests/str.rs",
    "content": "use rand::distr::StandardUniform;\nuse rand::{Rng, SeedableRng};\nuse rand_xorshift::XorShiftRng;\nuse rayon::prelude::*;\n\nfn seeded_rng() -> XorShiftRng {\n    let mut seed = <XorShiftRng as SeedableRng>::Seed::default();\n    (0..).zip(seed.as_mut()).for_each(|(i, x)| *x = i);\n    XorShiftRng::from_seed(seed)\n}\n\n#[test]\npub fn execute_strings() {\n    let rng = seeded_rng();\n    let s: String = rng\n        .sample_iter::<char, _>(&StandardUniform)\n        .take(1024)\n        .collect();\n\n    let par_chars: String = s.par_chars().collect();\n    assert_eq!(s, par_chars);\n\n    let par_even: String = s.par_chars().filter(|&c| (c as u32) & 1 == 0).collect();\n    let ser_even: String = s.chars().filter(|&c| (c as u32) & 1 == 0).collect();\n    assert_eq!(par_even, ser_even);\n\n    // test `FromParallelIterator<&char> for String`\n    let vchars: Vec<char> = s.par_chars().collect();\n    let par_chars: String = vchars.par_iter().collect();\n    assert_eq!(s, par_chars);\n\n    let par_bytes: Vec<u8> = s.par_bytes().collect();\n    assert_eq!(s.as_bytes(), &*par_bytes);\n\n    let par_utf16: Vec<u16> = s.par_encode_utf16().collect();\n    let ser_utf16: Vec<u16> = s.encode_utf16().collect();\n    assert_eq!(par_utf16, ser_utf16);\n\n    let par_charind: Vec<_> = s.par_char_indices().collect();\n    let ser_charind: Vec<_> = s.char_indices().collect();\n    assert_eq!(par_charind, ser_charind);\n}\n\n#[test]\npub fn execute_strings_split() {\n    // char testcases from examples in `str::split` etc.,\n    // plus a large self-test for good measure.\n    let tests = vec![\n        (\"Mary had a little lamb\", ' '),\n        (\"\", 'X'),\n        (\"lionXXtigerXleopard\", 'X'),\n        (\"||||a||b|c\", '|'),\n        (\"(///)\", '/'),\n        (\"010\", '0'),\n        (\"    a  b c\", ' '),\n        (\"A.B.\", '.'),\n        (\"A..B..\", '.'),\n        (\"foo\\r\\nbar\\n\\nbaz\\n\", '\\n'),\n        (\"foo\\nbar\\n\\r\\nbaz\", '\\n'),\n        (\"A few words\", ' '),\n        (\" Mary   had\\ta\\u{2009}little  \\n\\t lamb\", ' '),\n        (\"Mary had a little lamb\\nlittle lamb\\nlittle lamb.\", '\\n'),\n        (\"Mary had a little lamb\\nlittle lamb\\nlittle lamb.\\n\", '\\n'),\n        (include_str!(\"str.rs\"), ' '),\n    ];\n\n    macro_rules! check_separators {\n        ($split:ident, $par_split:ident) => {\n            for &(string, separator) in &tests {\n                let serial: Vec<_> = string.$split(separator).collect();\n                let parallel: Vec<_> = string.$par_split(separator).collect();\n                assert_eq!(serial, parallel);\n\n                let array = ['\\u{0}', separator, '\\u{1F980}'];\n                let array_ref = &array;\n                let slice: &[char] = array_ref;\n\n                let serial: Vec<_> = string.$split(slice).collect();\n                let parallel: Vec<_> = string.$par_split(slice).collect();\n                assert_eq!(serial, parallel);\n\n                let serial: Vec<_> = string.$split(array).collect();\n                let parallel: Vec<_> = string.$par_split(array).collect();\n                assert_eq!(serial, parallel);\n\n                let serial: Vec<_> = string.$split(array_ref).collect();\n                let parallel: Vec<_> = string.$par_split(array_ref).collect();\n                assert_eq!(serial, parallel);\n\n                let serial_fn: Vec<_> = string.$split(|c| c == separator).collect();\n                let parallel_fn: Vec<_> = string.$par_split(|c| c == separator).collect();\n                assert_eq!(serial_fn, parallel_fn);\n            }\n        };\n    }\n\n    check_separators!(split, par_split);\n    check_separators!(split_inclusive, par_split_inclusive);\n    check_separators!(split_terminator, par_split_terminator);\n\n    for &(string, _) in &tests {\n        let serial: Vec<_> = string.lines().collect();\n        let parallel: Vec<_> = string.par_lines().collect();\n        assert_eq!(serial, parallel);\n    }\n\n    for &(string, _) in &tests {\n        let serial: Vec<_> = string.split_whitespace().collect();\n        let parallel: Vec<_> = string.par_split_whitespace().collect();\n        assert_eq!(serial, parallel);\n    }\n\n    for &(string, _) in &tests {\n        let serial: Vec<_> = string.split_ascii_whitespace().collect();\n        let parallel: Vec<_> = string.par_split_ascii_whitespace().collect();\n        assert_eq!(serial, parallel);\n    }\n\n    // try matching separators too!\n    check_separators!(matches, par_matches);\n    check_separators!(match_indices, par_match_indices);\n}\n"
  }
]